#define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr
#define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
#define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
!
#include "tm5.inc"
#include "output.inc"  
!
!----------------------------------------------------------------------------
!                    TM5                                                    !
!----------------------------------------------------------------------------
!BOP
!
! !MODULE:      PHOTOLYSIS
!
! !DESCRIPTION: <add description>
!\\
!\\
! !INTERFACE: 
!
MODULE PHOTOLYSIS
  !
  ! !USES:
  !
  use GO,             only : gol, goPr, goErr
  use tm5_distgrid,   only : dgrid, Get_DistGrid, gather
  use photolysis_data
#ifdef with_optics
  use optics,         only : wavelendep
#endif

  IMPLICIT NONE
  PRIVATE
  !
  ! !PUBLIC MEMBER FUNCTIONS:
  !
  public :: photolysis_init, photolysis_done ! life cycle
  public :: ozone_info_online ! calculate the overhead ozone
  public :: aerosol_info      ! aerosol optical depths
  public :: slingo            ! cloud optical properties
  public :: update_csqy       ! update ...
  public :: daysim            ! calculate solar zenith angles
  public :: get_sza           ! return solar zenith angle (function)
  public :: photo_flux        ! calculates radiation fields
  public :: photorates_tropo  ! calculates photolysis and heating rates
#ifdef with_optics
  public :: aerosol_info_m7   ! aerosol optical depths
#endif
  !
  ! !PUBLIC DATA MEMBERS:
  !
  public                     :: phot_dat   ! type defined in photolysis_data
  !
  ! !PRIVATE DATA MEMBERS:
  !
  character(len=*), parameter  ::  mname = 'photolysis'

  real, parameter      :: todu = 3.767e-17                                ! from #/cm2 --> du
  real, parameter      :: to_m = 3.767e-22                                ! from #/cm2 --> m (for o2)
  real, parameter      :: sp   = 6.022e23*1.e-4*0.2095/(28.964*1e-3*9.81) ! sp from pa ---> #o2/cm2   

  logical                :: with_o3du

  real,dimension(122,34) :: xs_o3_look
  real,dimension( 65,34) :: xs_hno3_look,xs_pan_look,qy_o3_look 
  real,dimension( 45,34) :: xs_h2o2_look
  real,dimension( 55,34) :: xs_n2o5_look
  real,dimension( 89,34) :: xs_no2_look,qy_no2_look,qy_co_look
  real,dimension( 62,34) :: xs_no3_look
  real,dimension(105,34) :: xs_ch2o_look  ! local
  ! constants for acetone qy
  real,dimension(89,34)    ::   a1_acet,a2_acet,a3_acet,a4_acet
    
  integer                 :: l  
  real                    :: wl,x, ww

#ifdef with_optics
  type(wavelendep),dimension(:),allocatable :: wdep 
#endif

  !
  ! !REVISION HISTORY: 
  !   16 Jun 2011 - P. Le Sager - new version from JEW
  !   21 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  !    3 Oct 2012 - P. Le Sager - separate Init into true init and monthly update
  !    4 Mar 2013 - P. Le Sager - changes for optics feedback from NB
  !
  ! !REMARKS:
  !
  !EOP
  !--------------------------------------------------------------------------

CONTAINS

  ! Trap overflow
  function safe_div(n,d,altv) result(q)
    real, intent(in) :: n, d, altv
    real :: q

    if ( exponent(n)-exponent(d) >= maxexponent(n) .OR. d==0) then
       q=altv
    else
       q=n/d
    end if
  end function safe_div

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    INIT_PHOTOLYSIS
  !
  ! !DESCRIPTION:  read reference tables for photolysis, allocate photolysis
  !                data. Called from sources_sinks/Trace0 at the run start and
  !                at beginning of every month. 
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE PHOTOLYSIS_INIT( first, iunit, o3du )
    !
    ! !USES:
    !
    use dims,         only : im, jm, lm, nregions, newsrun
    use ParTools,     only : isRoot, par_broadcast
    use global_types, only : d23_data
    use global_data,  only : rcfile
    use MeteoData,    only : Set
    use MeteoData,    only : sp_dat, temper_dat, lsmask_dat, phlb_dat
    use MeteoData,    only : lwc_dat, iwc_dat, cc_dat, humid_dat, gph_dat
    use GO,           only : TrcFile, Init, Done, ReadRc
#ifdef with_optics
    use optics,       only : Optics_Init
#endif
    !
    ! !INPUT PARAMETERS:
    !
    logical,                                       intent(in) :: first   ! true init for a new run?
    integer,                                       intent(in) :: iunit
    type(d23_data), dimension(nregions), optional, intent(in) :: o3du 
    !
    ! !REVISION HISTORY: 
    !   21 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
    !
    ! !REMARKS:
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    integer            :: i,j,l,m,n,region,imr,jmr,lmr,i1, i2, j1, j2
    real               :: lat
    integer            :: status, wav
    type(TrcFile)      :: rcF
    character(len=256) :: photodir

    character(len=*), parameter  ::  rname = mname//'/photolysis_init'

    ! --- begin -------------------------

    with_o3du = present(o3du)

    !--------------------------------------------------
    ! ** TRUE INIT : only once
    !--------------------------------------------------        
    if (first) then

       REG: do region = 1, nregions

          call Set(     sp_dat(region), status, used=.true. ) 
          call Set( temper_dat(region), status, used=.true. )
          call Set(  humid_dat(region), status, used=.true. )
          call Set(    gph_dat(region), status, used=.true. )
          call Set(   phlb_dat(region), status, used=.true. )
          call Set(    lwc_dat(region), status, used=.true. ) 
          call Set(    iwc_dat(region), status, used=.true. ) 
          call Set(     cc_dat(region), status, used=.true. ) 
          call Set( lsmask_dat(region), status, used=.true. ) 

          ! allocate memory photolysis and initialise:
          call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
          lmr=lm(region)

          if (with_o3du) allocate( phot_dat(region)%o3klim_top(j1:j2) )

          allocate(phot_dat(region)%albedo    (i1:i2, j1:j2))     ; phot_dat(region)%albedo  = 0.05
          allocate(phot_dat(region)%ags_av    (i1:i2, j1:j2))     ; phot_dat(region)%ags_av  = 0.0
          allocate(phot_dat(region)%sza_av    (i1:i2, j1:j2))     ; phot_dat(region)%sza_av  = 0.0
          allocate(phot_dat(region)%lwp_av    (i1:i2, j1:j2,lmr)) ; phot_dat(region)%lwp_av  = 0.0
          allocate(phot_dat(region)%cfr_av    (i1:i2, j1:j2,lmr)) ; phot_dat(region)%cfr_av  = 0.0
          allocate(phot_dat(region)%reff_av   (i1:i2, j1:j2,lmr)) ; phot_dat(region)%reff_av = 0.0

          allocate(phot_dat(region)%aero_surface_clim(i1:i2, j1:j2)) ; phot_dat(region)%aero_surface_clim = 0

          phot_dat(region)%nalb_av   = 0.
          phot_dat(region)%ncloud_av = 0.
          phot_dat(region)%naer_av   = 0.

          allocate(phot_dat(region)%cloud_reff(i1:i2, j1:j2, lmr )) ; phot_dat(region)%cloud_reff = 0.0
          allocate(phot_dat(region)%pmcld     (i1:i2, j1:j2, lmr )) ; phot_dat(region)%pmcld      = 0.0
          allocate(phot_dat(region)%taus_cld  (i1:i2, j1:j2, lmr )) ; phot_dat(region)%taus_cld   = 0.0
          allocate(phot_dat(region)%taua_cld  (i1:i2, j1:j2, lmr )) ; phot_dat(region)%taua_cld   = 0.0 

          allocate(phot_dat(region)%pmaer     (i1:i2, j1:j2, lmr, nbands_trop, ngrid )) ; phot_dat(region)%pmaer    = 0.0
          allocate(phot_dat(region)%taus_aer  (i1:i2, j1:j2, lmr, nbands_trop, ngrid )) ; phot_dat(region)%taus_aer = 0.0
          allocate(phot_dat(region)%taua_aer  (i1:i2, j1:j2, lmr, nbands_trop, ngrid )) ; phot_dat(region)%taua_aer = 0.0         

          allocate(phot_dat(region)%pmcld_av    (i1:i2, j1:j2, lmr )) ; phot_dat(region)%pmcld_av    = 0.0
          allocate(phot_dat(region)%taus_cld_av (i1:i2, j1:j2, lmr )) ; phot_dat(region)%taus_cld_av = 0.0
          allocate(phot_dat(region)%taua_cld_av (i1:i2, j1:j2, lmr )) ; phot_dat(region)%taua_cld_av = 0.0 

          allocate(phot_dat(region)%pmaer_av    (i1:i2, j1:j2, lmr, nbands_trop,ngrid )) ; phot_dat(region)%pmaer_av    = 0.0
          allocate(phot_dat(region)%taus_aer_av (i1:i2, j1:j2, lmr, nbands_trop,ngrid )) ; phot_dat(region)%taus_aer_av = 0.0
          allocate(phot_dat(region)%taua_aer_av (i1:i2, j1:j2, lmr, nbands_trop,ngrid )) ; phot_dat(region)%taua_aer_av = 0.0   

          allocate(phot_dat(region)%jo3      (i1:i2, j1:j2, lmr )) ; phot_dat(region)%jo3       = 0.0
          allocate(phot_dat(region)%jno2     (i1:i2, j1:j2, lmr )) ; phot_dat(region)%jno2      = 0.0
          allocate(phot_dat(region)%jo3_av   (i1:i2, j1:j2, lmr )) ; phot_dat(region)%jo3_av    = 0.0
          allocate(phot_dat(region)%jno2_av  (i1:i2, j1:j2, lmr )) ; phot_dat(region)%jno2_av   = 0.0
          allocate(phot_dat(region)%jhno2    (i1:i2, j1:j2, lmr )) ; phot_dat(region)%jhno2     = 0.0
          allocate(phot_dat(region)%jhno2_av (i1:i2, j1:j2, lmr )) ; phot_dat(region)%jhno2_av  = 0.0
          allocate(phot_dat(region)%jch2oa   (i1:i2, j1:j2, lmr )) ; phot_dat(region)%jch2oa    = 0.0
          allocate(phot_dat(region)%jch2oa_av(i1:i2, j1:j2, lmr )) ; phot_dat(region)%jch2oa_av = 0.0
          allocate(phot_dat(region)%jch2ob   (i1:i2, j1:j2, lmr )) ; phot_dat(region)%jch2ob    = 0.0
          allocate(phot_dat(region)%jch2ob_av(i1:i2, j1:j2, lmr )) ; phot_dat(region)%jch2ob_av = 0.0             

          phot_dat(region)%nj_av = 0

          ! absorption cross-sections
          allocate(phot_dat(region)%v2         (i1:i2, j1:j2, lmr+1  )) ; phot_dat(region)%v2          = 0.0
          allocate(phot_dat(region)%v3         (i1:i2, j1:j2, lmr+1  )) ; phot_dat(region)%v3          = 0.0
          allocate(phot_dat(region)%v3_surf    (i1:i2, j1:j2         )) ; phot_dat(region)%v3_surf     = 0.0
          allocate(phot_dat(region)%qy_ch3cocho(i1:i2, j1:j2, lmr, 52)) ; phot_dat(region)%qy_ch3cocho = 0.0
          allocate(phot_dat(region)%qy_c2o3    (i1:i2, j1:j2, lmr, 89)) ; phot_dat(region)%qy_c2o3     = 0.0

          ! SAD fields
          phot_dat(region)%nsad_av   = 0
          allocate(phot_dat(region)%sad_cld    (i1:i2, j1:j2, lmr)) ; phot_dat(region)%sad_cld  = 0.0
          allocate(phot_dat(region)%sad_ice    (i1:i2, j1:j2, lmr)) ; phot_dat(region)%sad_ice  = 0.0
          allocate(phot_dat(region)%sad_aer    (i1:i2, j1:j2, lmr)) ; phot_dat(region)%sad_aer  = 0.0
          allocate(phot_dat(region)%sad_cld_av (i1:i2, j1:j2, lmr)) ; phot_dat(region)%sad_cld_av  = 0.0
          allocate(phot_dat(region)%sad_ice_av (i1:i2, j1:j2, lmr)) ; phot_dat(region)%sad_ice_av  = 0.0
          allocate(phot_dat(region)%sad_aer_av (i1:i2, j1:j2, lmr)) ; phot_dat(region)%sad_aer_av  = 0.0
          
       end do REG

       ! read settings from rcfile:
       call Init( rcF, rcfile, status )
       call ReadRc( rcF, 'input.photo', photodir, status )

       !--------------------------------------------------------------------   
       !     wavelengths in the middle of the intervals                        
       !--------------------------------------------------------------------   
       !     see: C. Bruehl, P.J. Crutzen, Scenarios of possible changes in ...
       !          Climate Dynamics (1988)2: 173-203 
       ! ONLINE TUNING : first 13 wavelength bins are now ignored. Grid also shortened above 690nm.

       do l=1,13 
          wave_full(l)=1./(56250.-500.*l) 
       end do

       do l=14,45 
          wave_full(l)=1./(49750.-(l-13)*500.) 
       end do

       do l=46,68 
          wave_full(l)=(266.+(l-13))*1.e-7 
       end do

       do l=69,71 
          wave_full(l)=(320.5+2.*(l-68))*1.e-7 
       end do
       do l=72,176 
          wave_full(l)=(325.+5.*(l-71))*1.e-7 
       end do

       do l=2,maxwav-1 
          dwave_full(l)=0.5*(wave_full(l+1)-wave_full(l-1))
       end do
       dwave_full(1)      = dwave_full(2) 
       dwave_full(maxwav) = dwave_full(maxwav-1) 
       ! select a subset from the full spctral grid to remove the first band      
       wave=wave_full(14:135)
       dwave=dwave_full(14:135)

       !---------------------------------------------------------------------  
       !     Rayleigh scattering cross sections                                
       !     emp. formula of Nicolet   plan. space sci.32, 1467f (1984)        
       !---------------------------------------------------------------------  

       do  l=1,maxwav                         
          wl=wave(l)*1.e4                   
          x=0.389*wl+0.09426/wl-0.3228      
          cs_ray(l)=4.02e-28/wl**(4.+x)     
       end do

       !--------------------------------------------------------------         
       !    Read and store temperature dependent cross-section values
       !--------------------------------------------------------------         

       open(unit=7,  file=trim(photodir)//'/tropo_look_up_modified_cb05.dat',     status='old')
       read(7,*)
       read(7,*)        
       read(7,*)
       do i=1,34
          read(7,'(176(1Pe10.3))') (xs_o3_look(wav,i),wav=1,122)
       enddo
       read(7,*)
       do i=1,34
          read(7,*) (xs_no2_look(wav,i),wav=1,89)
       enddo
       read(7,*)
       do i=1,34
          read(7,*) (xs_hno3_look(wav,i),wav=1,65)
       enddo
       read(7,*)
       do i=1,34
          read(7,*) (xs_h2o2_look(wav,i),wav=1,45)
       enddo
       read(7,*)
       do i=1,34
          read(7,*) (xs_n2o5_look(wav,i),wav=1,55)
       enddo
       read(7,*)
       do i=1,34
          read(7,*) (xs_ch2o_look(wav,i),wav=1,90)
       enddo
       read(7,*)
       do i=1,34
          read(7,*) (xs_pan_look(wav,i),wav=1,65)
       enddo
       read(7,*)
       do i=1,34
          read(7,*) (xs_no3_look(wav,i),wav=1,62)
       enddo
       read(7,*)
       do i=1,34
          read(7,*) (qy_o3_look(wav,i),wav=1,65)
       enddo
       read(7,*)
       do i=1,34
          read(7,*)(qy_no2_look(wav,i),wav=1,89)
       enddo
       read(7,*)
       do i=1,34
          read(7,*)(qy_co_look(wav,i),wav=1,89)
       enddo
       read(7,*)
       do i=1,34
          read(7,*)(a1_acet(wav,i),wav=1,89)
       enddo
       read(7,*)
       do i=1,34
          read(7,*)(a2_acet(wav,i),wav=1,89)
       enddo
       read(7,*)
       do i=1,34
          read(7,*)(a3_acet(wav,i),wav=1,89)
       enddo
       read(7,*)
       do i=1,34
          read(7,*)(a4_acet(wav,i),wav=1,89)
       enddo
       close(7)
       
       ! put constants in correct units
       a1_acet=a1_acet*1e-18
       a2_acet=a2_acet*1e-17
       a4_acet=a4_acet*1e-15        

       !--------------------------------------------------------------         
       !    Read and store temperature dependent cross-section values

       !------------------ extraterrestrial flux from input file ------------------

!        open(unit=7,  file=trim(photodir)//'/OMI.data.reduce',status='old')     
!        read(7,*)
!        read(7,'(1p7e10.2)') flux 
!        close(7)
       
       ! Cannot be read for some unknown reason on cca@ecmwf with cray compiler.
       ! Just set it here:

       flux=(/ 2.351E+12, 2.414E+12, 2.360E+12, 3.004E+12, 8.861E+12, 4.475E+12, 9.005E+12, & 
               1.607E+13, 1.556E+13, 1.221E+13, 2.061E+13, 2.070E+13, 1.047E+13, 7.497E+12, & 
               1.729E+13, 9.523E+12, 2.018E+13, 2.265E+13, 1.275E+13, 1.750E+13, 2.590E+13, & 
               8.777E+13, 2.193E+13, 5.449E+13, 1.074E+14, 6.856E+13, 7.875E+13, 2.275E+13, & 
               1.488E+14, 2.166E+14, 2.518E+14, 3.504E+14, 1.493E+14, 5.366E+13, 4.045E+13, & 
               2.054E+13, 6.274E+13, 9.589E+13, 1.326E+14, 1.307E+13, 1.332E+14, 1.729E+14, & 
               1.349E+14, 5.685E+13, 1.342E+14, 1.391E+14, 8.107E+13, 1.459E+14, 1.965E+14, & 
               5.681E+13, 1.349E+14, 6.819E+13, 2.137E+14, 1.564E+14, 1.334E+14, 3.559E+14, & 
               2.593E+14, 4.187E+14, 7.893E+14, 1.610E+14, 1.021E+15, 9.119E+14, 1.056E+15, & 
               8.424E+14, 6.622E+14, 9.387E+14, 1.463E+15, 3.382E+14, 1.076E+15, 9.586E+14, & 
               1.783E+15, 8.718E+14, 1.864E+15, 1.661E+15, 1.938E+15, 2.101E+15, 2.058E+15, & 
               1.738E+15, 9.227E+14, 2.404E+15, 2.176E+15, 2.625E+15, 2.167E+15, 1.741E+15, & 
               2.424E+15, 1.531E+15, 1.819E+15, 2.625E+15, 2.293E+15, 2.570E+15, 2.619E+15, & 
               2.663E+15, 2.705E+15, 2.542E+15, 1.331E+15, 2.633E+15, 2.575E+15, 2.744E+15, & 
               1.958E+15, 2.642E+15, 2.691E+15, 2.646E+15, 2.720E+15, 2.703E+15, 1.188E+15, & 
               2.720E+15, 2.271E+15, 2.405E+15, 2.723E+15, 2.690E+15, 2.550E+15, 2.670E+15, & 
               2.665E+15, 2.702E+15, 2.653E+15, 2.658E+15, 2.691E+15, 2.593E+15, 2.646E+15, & 
               2.653E+15, 2.636E+15, 2.648E+15 /)
       

#ifdef with_optics

       ! define wavelengths for optics calculations
       nwdep = nbands_trop + count(lmid.ne.lmid_gridA)
       wav_grid  = 0
       wav_gridA = 0
       allocate(photo_wavelengths(nwdep))

       l=1
       do i=1,nbands_trop
          if (lmid(i)==lmid_gridA(i)) then
             photo_wavelengths(l) = wave(lmid(i))*1.e4 ! cm to um
             wav_grid(i) = l
             wav_gridA(i) = l
             l=l+1   
          else
             photo_wavelengths(l) = wave(lmid(i))*1.e4 ! cm to um
             photo_wavelengths(l+1) = wave(lmid_gridA(i))*1.e4 ! cm to um
             wav_grid(i) = l
             wav_gridA(i) = l+1
             l=l+2
          endif
       enddo
              
       allocate(wdep(nwdep))
       wdep(:)%wl = photo_wavelengths
       wdep(:)%split = .false.
       wdep(:)%insitu = .false.
       
       call Done( rcF, status )
       IF_NOTOK_RETURN(status=1)
       
       CALL OPTICS_INIT( nwdep, wdep, status )
       IF_NOTOK_RETURN(status=1)
       
       deallocate(photo_wavelengths)
       
#else  
       !**************************************************************************
       !     aerosol data from: "Models for Aerosols of the Lower Atmosphere   
       !     and the Effects of Humidity Variations on their Optical Properties
       !     E. P. Shettle and R. W. Fenn (1979), Environmental Research Paper 
       !     No. 676                                                           
       !************************************************************************** 

       open(unit=7,  file=trim(photodir)//'/aerosol_reduce.dat',status='old')
       do l = 1,4
          read(7,*)
          do i = 1,8
             read(7,*)
             read(7,20)(ext(wav,i,l),wav=1,maxwav)        
             read(7,20)(abs_eff(wav,i,l),wav=1,maxwav)
             read(7,20)(g(wav,i,l),wav=1,maxwav)
             do wav=1,maxwav
                sca(wav,i,l) = ext(wav,i,l) - abs_eff(wav,i,l)
             enddo
          enddo
       enddo
       close(7) 

20     format(6(1X,F7.5))

       do l=1,maxwav
          do i=1,8
             do j=1,4
                sca(l,i,j) = sca(l,i,j)/pn_ref(j)*1.E-5
                abs_eff(l,i,j) = abs_eff(l,i,j)/pn_ref(j)*1.E-5
             end do
          end do
       end do

       ! close rc file
       call Done( rcF, status )
#endif
       
    ELSE ! NEWSRUN


       !--------------------------------------------------
       ! ** MONTHLY UPDATE 
       !--------------------------------------------------    

       if (with_o3du) then
          do region = 1, nregions             
             call Get_DistGrid( dgrid(region), J_STRT=j1, J_STOP=j2 )
             phot_dat(region)%o3klim_top(:) = o3du(region)%d23(j1:j2,lm(region))
          end do
       end if

    ENDIF

  END SUBROUTINE PHOTOLYSIS_INIT
  !EOC

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:   DAYSIM
  !
  ! !DESCRIPTION: Get all solar zenith angles (THA) for a given Julian day
  !                (DAYNR) at 1/6, 3/6(=center), and 5/6 of each grid box.
  !                THA is three times oversampled. 
  !                The longitudinal variation is equal to the simulation of
  !                one day, and covers the [-180,180] range for all regions.
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE DAYSIM(region, daynr, is, i1,i2,j1, j2, tha)
    !
    ! !USES:
    !
    use dims,      only : im, jm, xbeg, xend
    use binas,     only : pi
    use meteodata, only : lli
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in)   :: daynr, region, is, j1, j2,i1,i2
    !
    ! !OUTPUT PARAMETERS:
    !
    real,    intent(out)  :: tha( im(region)*3, j1:j2)
    !
    ! !REVISION HISTORY: 
    !   26 Apr 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
    !
    ! !REMARKS:
    !   (1) The regions are artificially expanded to cover all longitudes, in
    !       order to keep the correspondance b/w time and longitude.
    !   (2) Need to be called once a day only. Hence separated from GET_SZA,
    !       and the need to have 'im_alt' and 'shift' defined module wide.
    !   (3) Input 'is' is not i1=I_START from the distributed grid, but: (i1-1)*3+1
    !       It is not used yet. To delete?
    !   (4) Considering the cshift functions used on THA in GET_SZA, it is
    !       assumed that THA covers the entire longitude range.
    !EOP
    !------------------------------------------------------------------------
    !BOC

    real, dimension(j1:j2)  :: lat
    real                    :: houra, rdecl, sinhh, eqr, ut
    real                    :: piby, lon, tz, sintz, costz
    real                    :: sin2tz, cos2tz, sin3tz, cos3tz
    integer                 :: i, j, k
    !
    !call Get_DistGrid( dgrid(region), I_STOP=i2, J_STOP=j2 )
    
    piby = pi/180.
    !
    ! latitude range in radian
    lat  = lli(region)%lat
    !
    tz = 2.*pi*daynr/365.
    !
    ! Solar declination approximation 
    !(p.97, Brasseur et al, Atmospheric Chemistry and Global Change, 1999)
    !
    rdecl = -0.4*cos(2.*pi*real(daynr+10)/365.)
    !
    sintz = sin(tz)
    costz = cos(tz)
    sin2tz = 2.*sintz*costz
    cos2tz = costz*costz-sintz*sintz

    eqr = 0.000075 + 0.001868*costz  - 0.032077*sintz &
         - 0.014615*cos2tz - 0.040849*sin2tz
    !
    ! the sza variation over longitude [-180,180] at ut=12 equals
    ! a with variation of ut over [0,24] at longitude 0:
    ! houra = 15.*(ut-12. + eqr*24./(2.*pi) + lon*24./360)*piby
    !
    
    ! THA (sampled at 1/6, 3/6, and 5/6 of each box). As follow for 6 degree resolution:
    !
    !     -180---+---+---177---+---+---174---+---+---171---+---+---168  .......etc...
    !       |                           |                           |
    !       |        box #1             |          box #2           |
    !       |                           |                           |
    !       +---------------------------+---------------------------+   .......etc.....
    !       0    1   2    3    4   5    0    1   2    3    4   5
    !            *        *        *         *        *        *         <---- samples (lon,THA)    
    do j=j1,j2
       do i=1,im(region)*3
          lon      = -180. + (real(i)-0.5)*360./real(im(region)*3)
          !lon      = xbeg(region) + (real(i)-0.5)*(xend(region)-xbeg(region))/real(im(region)*3)
          houra    = -pi + lon*piby + eqr
          sinhh    = sin(rdecl)*sin(lat(j)) &
               + cos(rdecl)*cos(lat(j))*cos(houra)
          tha(i,j) = acos(sinhh)/piby
       enddo
    enddo
    
  END SUBROUTINE DAYSIM
  !EOC

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    GET_SZA
  !
  ! !DESCRIPTION: 
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE GET_SZA(region, i1, j1, i2, j2, tstart, deltat, tha, sza)
    !
    ! !USES:
    !
    use dims, only : im, jm
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in)  :: region, i1, j1, i2, j2
    real,    intent(in)  :: tstart                  ! start time of chemistry timestep     
    real,    intent(in)  :: deltat                  ! chemistry timestep in hours          
    real,    intent(in)  :: tha(im(region)*3,j1:j2) ! three times oversampled zenith angles
    !
    ! !OUTPUT PARAMETERS:
    !
    real,    intent(out) :: sza(i1:i2,j1:j2)     ! effective solar zenith angles for this timestep
    !
    ! !REVISION HISTORY: 
    !   26 Apr 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
    !
    ! !REMARKS:
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    real, dimension(im(region)*3,j1:j2) :: mu3
    real                                :: dt
    integer                             :: it, i, ii
    !
    mu3 = 0.0
    !
    ! split chemistry timestep in intervals and calculate mu at 1/6, 3/6
    ! and 5/6 of timestep chemistry. Interpolate in time using the
    ! longitudinal dependence of tha and take the average.
    !
    do ii=1,5,2
       dt = ( tstart + ii*deltat/6. ) * (real(im(region)*3)/24.)
       it = int(dt)   
       dt = dt-it
       mu3  = mu3 + (1-dt)*cshift(tha,it,1)+dt*cshift(tha,it+1,1)
    enddo
    !
    ! average over three angles at three times resolution
    !
    do i=i1,i2
       sza(i,:) = (mu3(i*3-2,:) + mu3(i*3-1,:) + mu3(i*3,:))/9.0
    enddo

  END SUBROUTINE GET_SZA
  !EOC

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    PHOTO_FLUX
  !
  ! !DESCRIPTION: 
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE PHOTO_FLUX( region, is, js, sza, rj_new)
    !********************************************************************** 
    !                                                                     * 
    !     contact:                                                        * 
    !                                                                     *
    !     Jason Williams                                                  * 
    !     Koninklijk Nederlands Meteorologisch instituut (KNMI)           *
    !     Postbus 201                                                     *
    !     3730 AE De Bilt                                                 *
    !     tel +31 (0)30 2206748                                           * 
    !     e-mail : williams@knmi.nl                                       *
    !                                                                     *
    !********************************************************************** 
    ! purpose:
    !
    ! The calculation of the radiation fields using input from TM5 and ECMWF meteo.
    !
    ! method: 
    !
    ! Optical properties (optical thickness,cross sections, quantum yields)
    ! are calculated for lm(region) layers. Radiation fluxes are derived for 0:lm(region)
    ! levels, including the surface and top of atmosphere. Thus, level l overlays layer l.
    ! Photolysis rates in a layer are evaluated by taking the average of the
    ! photolysis rates evaluated at the upper and lower boundaries of the layer.
    !
    ! First, spectral calculations are performed for an atmosphere with absorption
    ! only, including gaseous absorption by O2 and O3 and aerosol absorption.
    ! Second, a correction is applied for scattering and surface reflection, per
    ! scattering band and using radiative transfer calculations at representative
    ! wavelengths 
    !
    ! This photolysis module is based on:
    !
    !     Landgraf and Crutzen, 1998, J. Atmos. Sci, 55, 863-878.
    !     Williams et al., 2006, Atmos.Chem.Phys., 6, 4137-4161.   
    !
    !------------------------------------------------------------------
    !
    ! Albedo field
    ! ------------
    !
    ! In older TM photolysis code, an adhoc uv-vis albedo was computed
    ! from land cover fields:
    !
    !   module dry_deposition
    !     dd_surface_fields
    !       if(root_k)then
    !         dd_calc_inisurf
    !           compute ags on glb1x1 from land cover, on root_k only
    !         dd_coarsen_vd
    !           coarsen ags to vd_temp, copy into phot_dat(region)%albedo
    !       endif
    !       broadcast phot_dat(region)%albedo to all other processors
    !       
    ! In the first stratospheric codes, the same adhoc albedo computed in 
    ! drydepos was written over the albedo meteo field, and then this one was used.
    ! To avoid this obscure destruction of ecmwf data, we use the phot_dat version here.
    ! In future, this should be replaced by ECMWF field:
    !     UV visible albedo for direct radiation  ALUVP         (0 - 1)         15      128 
    !
    !------------------------------------------------------------------ 
    ! subroutine to calculate direct flux and actinic flux
    !*******************************************************************        
    !
    ! !USES:
    !
    use dims,      only : lm, idate, ndyn, ndyn_max
    use MeteoData, only : temper_dat, gph_dat, cc_dat
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in) :: region
    integer, intent(in) :: is, js
    real,    intent(in) :: sza(is:,js:)
    !
    ! !OUTPUT PARAMETERS:
    !
    !  photolysis rates for this time-step     
    real, dimension(is:,js:,:,:), intent(out) :: rj_new ! (i1:i2,j1:j2,lm(region),nj)
    !
    ! !REVISION HISTORY: 
    !   26 Apr 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    integer :: i, j, l, k, n, table_pos
    real    :: zangle, alb, esrm2
    real, dimension(lm(region)+1)   :: levels 
    logical                         :: clear, cloudy, debug_flag
    ! temperature index array for the lookup table
    integer, parameter              :: n_ind =34 ! number of increments in the look-up table
    integer, parameter              :: jindex=9
    integer, parameter              :: latindex=21
    real, parameter                 :: incr = 5. ! 5deg C intervals in look-up table (optimised value)
    real, dimension(n_ind)          :: temp_ind   

    real, dimension(:),    allocatable  :: v2_col, v3_col, dv2_col, dv3_col, t_lay, ly_a, column_cloud
    real, dimension(:,:),  allocatable  :: cst_o3_col
    real, dimension(:,:),  allocatable  :: cst_no2_col, qy_no2_col
    real, dimension(:,:),  allocatable  :: cst_hno3_col
    real, dimension(:,:),  allocatable  :: cst_h2o2_col
    real, dimension(:,:),  allocatable  :: cst_n2o5_col
    real, dimension(:,:),  allocatable  :: cst_ch2o_col 
    real, dimension(:,:),  allocatable  :: cst_pan_col
    real, dimension(:,:),  allocatable  :: cst_no3_col
    real, dimension(:,:),  allocatable  :: qy_o1d_col
    real, dimension(:,:),  allocatable  :: qy_ch3cocho_col
    real, dimension(:,:),  allocatable  :: qy_co_col,qy_c2o3_col     
    real, dimension(:,:),  allocatable  :: fdir, fact
    real, dimension(:),    allocatable  :: taua_cld_col, taus_cld_col
    real, dimension(:,:,:),allocatable  :: taus_aer_col, taua_aer_col
    real, dimension(:,:),  allocatable  :: ts_pi_clr_col, ta_pi_clr_col, g_pi_clr_col, g_pi_cld_col
    real, dimension(:),    allocatable  :: ts_pi_cld, ta_pi_cld 
    real, dimension(:,:,:),allocatable  :: pm_aer_col
    real, dimension(:),    allocatable  :: pm_cld_col
    real, dimension(:,:),  allocatable  :: ds
    real, dimension(:,:),  allocatable  :: rj_column   
    real, dimension(:,:,:),pointer      :: temperature
    ! additional diagnostic array to compare old/new jvalue input
    real, dimension(:), allocatable      :: vo3s_col
    real                                 :: zangle_in, rdif_szalims
    integer :: i1, j1, i2, j2

    call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )

    allocate( v2_col  (lm(region)+1) )
    allocate( v3_col  (lm(region)+1) )
    allocate( dv2_col (lm(region)  ) )
    allocate( dv3_col (lm(region)  ) )
    allocate( t_lay   (lm(region)  ) )
    allocate( cst_o3_col     (lm(region),maxwav) )
    allocate( cst_no2_col    (lm(region),89)     )
    allocate( qy_no2_col     (lm(region),89)     )
    allocate( qy_co_col      (lm(region),89)     )
    allocate( qy_c2o3_col    (lm(region),89)     )    
    allocate( cst_hno3_col   (lm(region),65)     )
    allocate( cst_h2o2_col   (lm(region),45)     )
    allocate( cst_n2o5_col   (lm(region),55)     )
    allocate( cst_ch2o_col   (lm(region),105)    )
    allocate( cst_pan_col    (lm(region),65)     )
    allocate( cst_no3_col    (lm(region),62)     )
    allocate( qy_o1d_col     (lm(region),65)     )
    allocate( qy_ch3cocho_col(lm(region),52)     )
    allocate( fdir           (lm(region),maxw)   ) ; fdir(:,:) = 0.
    allocate( taus_aer_col  (lm(region),nbands_trop,ngrid))
    allocate( taua_aer_col  (lm(region),nbands_trop,ngrid))
    allocate( taus_cld_col  (lm(region)))
    allocate( taua_cld_col  (lm(region)))
    allocate( ts_pi_clr_col (lm(region),nbands_trop))
    allocate( ta_pi_clr_col (lm(region),nbands_trop))
    allocate( g_pi_clr_col  (lm(region),nbands_trop))
    allocate( g_pi_cld_col  (lm(region),nbands_trop))
    allocate( pm_aer_col    (lm(region),nbands_trop,ngrid))
    allocate( pm_cld_col    (lm(region)))
    allocate( fact          (lm(region),nbands_trop)) ; fact(:,:) = 0.
    allocate( column_cloud  (lm(region)))
    allocate( ds            (lm(region)+1,lm(region)))
    allocate( rj_column     (lm(region),nj)) ; rj_column = 0.

    allocate(vo3s_col(lm(region)+1))

    temperature => temper_dat(region)%data

    clear = .false.
    cloudy = .true.
    debug_flag = .false.

    ! define temperature index array from the lookup table
    do i = 1, 34
       temp_ind(i) = 182.5 + (i-1) * 5.0
    enddo

    ! Inverse of SZA difference in limits,i.e. 1./(94-85)
    rdif_szalims = 1.0 / ( sza_widelimit - sza_limit )

    do j = j1, j2
       do i = i1, i2

          zangle = sza(i,j)
          ! Limit value used by photolysis computation to 'sza_limit' ...
          zangle_in = min( sza_limit, zangle )
          
          t_lay = temperature(i,j,:)

          rj_new(i,j,:,:) = 0.
          
          if ( zangle <= sza_widelimit ) then
             
             ! initialise
             fdir = 0. ; dv2_col = 0. ; dv3_col = 0. ; fact = 0.

             v2_col(:) = phot_dat(region)%v2(i,j,:)
             v3_col(:) = phot_dat(region)%v3(i,j,:)
             qy_ch3cocho_col(:,:) = phot_dat(region)%qy_ch3cocho(i,j,:,:)
             qy_c2o3_col(:,:) = phot_dat(region)%qy_c2o3(i,j,:,:)
             column_cloud(:) = cc_dat(region)%data(i,j,:)
             levels=gph_dat(region)%data(i,j,:)

             ! set optical depths parameters
             taus_cld_col =  phot_dat(region)%taus_cld(i,j,:) 
             taua_cld_col =  phot_dat(region)%taua_cld(i,j,:) 
             taus_aer_col =  phot_dat(region)%taus_aer(i,j,:,:,:) 
             taua_aer_col =  phot_dat(region)%taua_aer(i,j,:,:,:)
             pm_cld_col = phot_dat(region)%pmcld(i,j,:)  
             pm_aer_col = phot_dat(region)%pmaer(i,j,:,:,:) 

             !
             ! assign the cross-sections here to avoid the exporting of large arrays
             !   
             do k=1,lm(region)

                table_pos=int((t_lay(k) - (temp_ind(1)-0.5*5)) / 5) + 1
                table_pos=min(max(1,table_pos),34)  ! bug fix for temperatures below 175.5
                cst_o3_col(k,:) = xs_o3_look(:,table_pos)
                cst_no2_col(k,:) = xs_no2_look(:,table_pos)
                cst_hno3_col(k,:) = xs_hno3_look(:,table_pos)
                cst_h2o2_col(k,:) = xs_h2o2_look(:,table_pos)
                cst_ch2o_col(k,:) = xs_ch2o_look(:,table_pos)
                cst_n2o5_col(k,:) = xs_n2o5_look(:,table_pos)
                cst_pan_col(k,:) = xs_pan_look(:,table_pos)
                cst_no3_col(k,:) = xs_no3_look(:,table_pos)
                qy_o1d_col(k,:) = qy_o3_look(:,table_pos)
                qy_no2_col(k,:) = qy_no2_look(:,table_pos)
                qy_co_col(k,:) = qy_co_look(:,table_pos)                
             enddo

             ! slant column, lyman-alpha and direct flux ; all are zenith angle dependent

             call directflux(region,zangle_in,v2_col,v3_col,cst_o3_col,t_lay,fdir,dv2_col,dv3_col,taua_cld_col, &
                  taua_aer_col,levels,ds,vo3s_col,debug_flag)

             ! now do radiative transfer calculation, calculate actinic flux
             ! set albedo
             alb = phot_dat(region)%albedo(i,j)

             ! Now call the PIFM RT solver for the online calculation ; both clear and cloudy conditions can be used

             if  (clear) call pifm(region,zangle_in,alb,cst_o3_col,dv2_col,dv3_col, &
                  taua_aer_col,taus_aer_col,pm_aer_col,fact)
             if (cloudy) call pifm_ran( region,zangle_in,alb,cst_o3_col,dv2_col,dv3_col, &
                  taua_cld_col,taus_cld_col,pm_cld_col,taua_aer_col,taus_aer_col,pm_aer_col,fact,column_cloud)

             rj_column=0.

             call photorates_tropo(region,zangle_in,cst_o3_col,cst_no2_col,cst_hno3_col,cst_h2o2_col,cst_ch2o_col,&
                  cst_n2o5_col,cst_pan_col,cst_no3_col,qy_no2_col,qy_o1d_col,qy_ch3cocho_col,qy_co_col,qy_c2o3_col, &
                  fact,fdir,rj_column,t_lay,debug_flag) 

             if ( zangle <= sza_limit) then
                ! If actual SZA is below 85 deg then use values as such...
                rj_new(i,j,:,:) = rj_column
             else
                ! Otherwise, with SZA is between 85 deg and 95 then use interpolated values 
                rj_new(i,j,:,:) = rj_column * (sza_widelimit - zangle) * rdif_szalims
             end if

          elseif(zangle > sza_widelimit) then

             vo3s_col = 0.

             do k=1,lm(region)
                table_pos=int((t_lay(k) - (temp_ind(1)-0.5*5)) / 5) + 1  
                table_pos=min(max(1,table_pos),34)  ! max(...) == temperatures below 175.5 used like 180.5
                cst_o3_col(k,:) = xs_o3_look(:,table_pos)
             enddo

             debug_flag=.false.

          endif ! sza_limit

       enddo ! i
    enddo  ! j 


    ! Correction photolysis for distance sun-earth
    esrm2 = sundis(idate(2),idate(3))
    rj_new = rj_new *esrm2

    ! Store
    phot_dat(region)%jo3 (:,:,:) = rj_new(:,:,:,jo3d) 
    phot_dat(region)%jno2 (:,:,:) = rj_new(:,:,:,jno2)
    phot_dat(region)%jhno2 (:,:,:) = rj_new(:,:,:,jhono)
    phot_dat(region)%jch2oa (:,:,:) = rj_new(:,:,:,jach2o)
    phot_dat(region)%jch2ob (:,:,:) = rj_new(:,:,:,jbch2o)
    
    ! Averages
    phot_dat(region)%nj_av     = phot_dat(region)%nj_av   + float(ndyn)/float(ndyn_max)
    phot_dat(region)%nalb_av   = phot_dat(region)%nalb_av + float(ndyn)/float(ndyn_max)
    phot_dat(region)%jo3_av    = phot_dat(region)%jo3_av  + float(ndyn)/float(ndyn_max) * rj_new(:,:,:,jo3d) 
    phot_dat(region)%jno2_av   = phot_dat(region)%jno2_av + float(ndyn)/float(ndyn_max) * rj_new(:,:,:,jno2)
    phot_dat(region)%jhno2_av  = phot_dat(region)%jhno2_av + float(ndyn)/float(ndyn_max) * rj_new(:,:,:,jhono)
    phot_dat(region)%jch2oa_av = phot_dat(region)%jch2oa_av + float(ndyn)/float(ndyn_max) * rj_new(:,:,:,jach2o)
    phot_dat(region)%jch2ob_av = phot_dat(region)%jch2ob_av + float(ndyn)/float(ndyn_max) * rj_new(:,:,:,jbch2o)
      
    phot_dat(region)%ags_av  = phot_dat(region)%ags_av  + float(ndyn)/float(ndyn_max) * phot_dat(region)%albedo
    phot_dat(region)%sza_av  = phot_dat(region)%sza_av  + float(ndyn)/float(ndyn_max) * sza

    ! Done
    nullify(temperature)

    deallocate(v2_col)
    deallocate(v3_col)
    deallocate(dv2_col)
    deallocate(dv3_col)
    deallocate(cst_o3_col)
    deallocate(cst_no2_col)
    deallocate(qy_no2_col)
    deallocate(qy_co_col)
    deallocate(qy_c2o3_col)
    deallocate(cst_hno3_col)
    deallocate(cst_h2o2_col)
    deallocate(cst_n2o5_col)
    deallocate(cst_ch2o_col)
    deallocate(cst_pan_col)
    deallocate(cst_no3_col)
    deallocate(qy_o1d_col)
    deallocate(qy_ch3cocho_col)
    deallocate(fdir)
    deallocate(t_lay)
    deallocate(taus_aer_col)
    deallocate(taua_aer_col)
    deallocate(pm_aer_col)
    deallocate(taus_cld_col)
    deallocate(taua_cld_col)
    deallocate(pm_cld_col)
    deallocate(ts_pi_clr_col)
    deallocate(ta_pi_clr_col)
    deallocate(g_pi_clr_col)
    deallocate(g_pi_cld_col)

    deallocate(fact)
    deallocate(column_cloud)
    deallocate(ds)
    deallocate(rj_column)

    deallocate(vo3s_col)


  END SUBROUTINE PHOTO_FLUX
  !EOC

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    DIRECTFLUX
  !
  ! !DESCRIPTION: 
  !         Schumann-Runge parameterization
  !         Koppers GAA, Murtagh DP, Ann. Geophysicae 14, 68-79
  !\\
  !\\
  ! !INTERFACE:
  !
  subroutine directflux(region,zangle,v2_col,v3_col,cst_o3_col,t_lay,&
       fdir,dv2_col,dv3_col,taua_cld_col,taua_aer_col,&
       levels,ds,vo3s_col,debug_flag)
    !
    ! !USES:
    !
    use dims,  only : lm
    use binas, only : pi, avog, grav, xmair, ae
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in)    :: region 
    real,intent(in)        :: zangle
    ! oxygen and ozone column
    real,dimension(lm(region)+1),intent(in)                   :: v2_col,v3_col
    real,dimension(lm(region)),intent(in)                     :: taua_cld_col
    real,dimension(lm(region),nbands_trop,ngrid),intent(in)   :: taua_aer_col
    !
    ! !OUTPUT PARAMETERS:
    !
    real,dimension(lm(region)+1),intent(out)                  :: vo3s_col
    ! temperature
    real,dimension(lm(region)),intent(in)                     :: t_lay
    ! temperature dependent cs of ozone
    real,dimension(lm(region),maxwav),intent(in)              :: cst_o3_col
    ! flux through pure absorbing atmosphere
    real,dimension(lm(region),maxw),intent(out)               :: fdir

    real,dimension(lm(region)),intent(out)                    :: dv2_col,dv3_col
    ! levels for ds calculation
    real,dimension(lm(region)+1)                              :: levels
    real,dimension(lm(region)+1,lm(region)),intent(out)       :: ds
    logical,intent(in)                                        :: debug_flag
    !
    ! !REVISION HISTORY: 
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    real,dimension(:),allocatable   :: t_lev  
    real,dimension(:),allocatable   :: v2s,v3s,dv2s, dv3s  
    integer                         :: l, li, i, j, k, k1, k2, id, n, h, bandno 
    real                            :: dl_o2,u0     
    real,dimension(20)              :: coeff_a, coeff_b 
    real                            :: a,b,c, gamma
    real,dimension(maxw)            :: fdir_top
    real                            :: fdir_bot
    real                            :: ta_o2, ta_o3, tau
    real                            :: sp, const, press, alp, alv2, sln, ck, sf  
    !-----------------------------------------------------------------     
    ! declarations for the calculation of DS
    real,dimension(0:lm(region))     :: ze
    real,dimension(0:lm(region),lm(region)) :: ds_tmp
    real                             :: rpsinz,rj,rjp1,diffj,height1,height2
    real                             :: zenrad,sm,re,dsj,dummy

    allocate(t_lev(lm(region)+1)) ; t_lev=0.
    allocate(dv2s(lm(region))) ; dv2s = 0.
    allocate(dv3s(lm(region))) ; dv3s = 0.
    allocate(v2s(1:lm(region)+1)) ; v2s = 0.
    allocate(v3s(1:lm(region)+1)) ; v3s = 0.

    ! initialise all output
    fdir = 0. ; dv2_col = 0 ; dv3_col = 0. ; ds = 0. ; ds_tmp = 0.

    ! define temperature on grid levels. Note temperature on layers now has reversed vertical grid
    do k  = 2,lm(region)
       t_lev(k) = (t_lay(k) + t_lay(k-1) ) * 0.5
    enddo

    ! boundaries
    t_lev(1) = t_lay(1) 
    t_lev(lm(region)+1) = t_lay(lm(region))

    a = 0.50572 ; b = 6.07995 ; c = 1.63640

    dv2_col(lm(region))  = v2_col(lm(region))      
    dv3_col(lm(region))  = v3_col(lm(region)) 

    do l=lm(region)-1,1,-1
       dv2_col(l)  = v2_col(l)-v2_col(l+1)
       dv3_col(l)  = v3_col(l)-v3_col(l+1) 
    end do

    !-----correction of the air mass factor---------------------------------                                                                       
    !     F. Kasten and T. Young, Revised optical air mass tabels and       
    !     approximation formula (1989) Aplied Optics Vol 28, No. 22 P. 4735 
    !     and J. Lenoble, atmospheric radiative transfer (1993), P. 236     
    !    define air mass factor in mu

    gamma = 90. - zangle
    u0 = sin(gamma*pi/180.) + a *(gamma+b)**(-c)        
    u0 = min(1.,u0)

    if(zangle <= 75.) then
       ds = 1/u0
    elseif(zangle >75. .and. zangle <=sza_limit) then
       levels(1:lm(region)+1)=levels(lm(region)+1:1:-1)

       re = (ae+levels(lm(region)+1))*1.e-3

       do k=lm(region)+1,1,-1
          ze(k-1) = (levels(k)/1.e3)-(levels(lm(region)+1)/1.e3)
       enddo

       zenrad=acos(u0)

       do k=0,lm(region)
          rpsinz = (re+ze(k))*sin(zenrad)

          id = k
          do n=1,id
             sm = 1.0
             rj = re + ze(n-1)
             rjp1 = re + ze(n)

             diffj = ze(n-1) - ze(n)

             height1 = rj**2 - rpsinz**2
             height2 = rjp1**2 - rpsinz**2

             height1=max(0.0,height1)
             height2=max(0.0,height2)

             if(id>k .and. n==id) then
                dsj=sqrt(height1)
             else
                dsj=sqrt(height1)-sm*sqrt(height2)
             endif

             ds_tmp(k,n) = dsj/diffj

          enddo ! n
       enddo !k
       ! invert matrix to be compatible with lm(region)+1 being tOA
       ds(1:lm(region)+1,1:lm(region))=ds_tmp(lm(region):0:-1,lm(region):1:-1)
    ENDIF ! sza_rad   

    ! slant column : calculate in different way depending on zangle
    if(zangle <=75.) then 
       v2s(lm(region)+1)=ds(lm(region),lm(region))*v2_col(lm(region)+1)  
       v3s(lm(region)+1)=ds(lm(region),lm(region))*v3_col(lm(region)+1) 
       do k1=lm(region)+1,1,-1 
          v2s(k1) = v2s(lm(region)+1)
          v3s(k1) = v3s(lm(region)+1)

          do k2=lm(region),k1,-1
             v2s(k1) = v2s(k1) + ds(k1,k2)*dv2_col(k2)    
             v3s(k1) = v3s(k1) + ds(k1,k2)*dv3_col(k2)    
          end do
       end do
    elseif(zangle>75. .and. zangle<=85.) then
       v2s(lm(region)+1) = ds(lm(region),lm(region))*v2_col(lm(region)+1)
       v3s(lm(region)+1) = ds(lm(region),lm(region))*v3_col(lm(region)+1)
       do k1=lm(region)+1,1,-1
          v2s(k1) = v2s(lm(region)+1)
          v3s(k1) = v3s(lm(region)+1)
          do k2=lm(region),1,-1
             v2s(k1) = v2s(k1) + ds(k1,k2)*dv2_col(k2)    
             v3s(k1) = v3s(k1) + ds(k1,k2)*dv3_col(k2)
          enddo
       enddo
    endif

    do k1=lm(region)+1,1,-1
       vo3s_col(k1)=v3s(k1)
    enddo

    ! differential slant column
    dv2s(lm(region)) = v2s(lm(region))-v2s(lm(region)+1)
    dv3s(lm(region)) = v3s(lm(region))-v3s(lm(region)+1)    
    do k = lm(region)-1,1,-1
       dv2s(k) = v2s(k)-v2s(k+1)     
       dv3s(k) = v3s(k)-v3s(k+1)
       if(dv2s(k)<0.) dv2s(k)=-1.0*dv2s(k) 
       if(dv3s(k)<0.) dv3s(k)=-1.0*dv3s(k)   
    enddo

    ! intialise direct flux
    fdir_top(1:maxw) = flux(1:maxw)     
    ! direct flux = actinic flux for a purely abs. atmosphere
    ! here, layer averaged quantity 

    bandno=1

    if(zangle <=85.) then
       do l = 1,maxw
          do k = lm(region),1,-1 
             if(l<18) then
                ta_o2 = cross_o2(l)*dv2s(k)
             else
                ta_o2 = 0.
             endif
             ta_o3 = cst_o3_col(k,l)*dv3s(k)
             fdir_bot  = fdir_top(l) * exp(-ta_o2-ta_o3-taua_cld_col(k)-taua_aer_col(k,bandno,1)) 
             fdir(k,l) = (fdir_top(l) + fdir_bot)/2.
             fdir_top(l) = fdir_bot
             if(l>lfin(bandno)) bandno=bandno+1 
          enddo
       enddo
    endif

    deallocate(t_lev)
    deallocate(v2s)
    deallocate(v3s)
    deallocate(dv2s)
    deallocate(dv3s)

  END SUBROUTINE DIRECTFLUX
  !EOC
  
#ifdef with_optics
  ! only define when coupling with photolysis is turned on
  
  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    AEROSOL_INFO_M7
  !
  ! !DESCRIPTION: assignment of aerosol optical depths calculated in M7  
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE AEROSOL_INFO_M7(region, status)
    !
    ! !USES:
    !
    USE TM5_DISTGRID, ONLY : dgrid, Get_DistGrid
    USE DIMS,         ONLY : isr,ier,jsr,jer, ndyn_max, ndyn
    USE METEODATA,    ONLY : gph_dat
    USE DIMS,         ONLY : im, jm, lm
    USE OPTICS,       ONLY : optics_aop_get
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in)  :: region
    !
    ! !OUTPUT PARAMETERS:
    !
    integer, intent(out) ::  status
    !
    ! !REVISION HISTORY: 
    !      Aug 2012 - NB
    !    5 Mar 2013 - Ph. Le Sager - TM5-MP version
    !
    ! !REMARKS:
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    character(len=*), parameter  ::  rname = mname//'/aerosol_info_m7'

    integer                               :: i,j,l,lvec, nsend, igrid, i1, i2, j1, j2, lmr
    real, dimension(:,:,:),   pointer     :: gph
    real, dimension(:,:,:,:), allocatable :: taus_aer, taua_aer, pmaer

    ! Optics output fields (to be used and allocated by methods using the optics)
    real, dimension(:,:,:),   allocatable :: aop_out_ext ! extinctions
    real, dimension(:,:),     allocatable :: aop_out_a   ! single scattering albedo
    real, dimension(:,:),     allocatable :: aop_out_g   ! assymetry factor

    ! ------------ begin -----------------
    
    ! count lvec, tile grid size
    CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
    lmr=lm(region)
    lvec = (i2-i1+1)*(j2-j1+1)*lmr

    allocate( aop_out_ext(lvec, nwdep, 1))
    allocate( aop_out_a  (lvec, nwdep)   )
    allocate( aop_out_g  (lvec, nwdep)   )

    CALL OPTICS_AOP_GET(lvec, region, nwdep, wdep, 1, .false., &
                        aop_out_ext, aop_out_a, aop_out_g, status)
    IF_NOTOK_RETURN(status=1)

    gph => gph_dat(region)%data

    allocate(taus_aer (i1:i2, j1:j2, lmr,nwdep)); taus_aer = 0.0
    allocate(taua_aer (i1:i2, j1:j2, lmr,nwdep)); taua_aer = 0.0  
    allocate(pmaer    (i1:i2, j1:j2, lmr,nwdep)); pmaer    = 0.0

    ! ---------------------------------
    ! unpack results from calculate_aop   
    ! ---------------------------------
    lvec = 0
    do l = 1, lmr
    do j = j1,j2
    do i = i1,i2

       lvec = lvec + 1

       taus_aer(i,j,l,1:nwdep) = aop_out_ext(lvec,1:nwdep,1) * aop_out_a(lvec,1:nwdep) * (gph(i,j,l+1) - gph(i,j,l))       ! from 1/m to nondim
       taua_aer(i,j,l,1:nwdep) = aop_out_ext(lvec,1:nwdep,1) * (1.-aop_out_a(lvec,1:nwdep)) * (gph(i,j,l+1) - gph(i,j,l))
       pmaer   (i,j,l,1:nwdep) = aop_out_g  (lvec,1:nwdep)
       
    enddo
    enddo
    enddo

    nullify(gph)

    do i=1, nbands_trop
       phot_dat(region)%taus_aer(:,:,:,i,1) = taus_aer(:,:,:,wav_grid(i))
       phot_dat(region)%taua_aer(:,:,:,i,1) = taua_aer(:,:,:,wav_grid(i))
       phot_dat(region)%pmaer   (:,:,:,i,1) = pmaer   (:,:,:,wav_grid(i))

       phot_dat(region)%taus_aer(:,:,:,i,2) = taus_aer(:,:,:,wav_gridA(i))
       phot_dat(region)%taua_aer(:,:,:,i,2) = taua_aer(:,:,:,wav_gridA(i))
       phot_dat(region)%pmaer   (:,:,:,i,2) = pmaer   (:,:,:,wav_gridA(i))
    enddo

    phot_dat(region)%naer_av     = phot_dat(region)%naer_av     + float(ndyn)/float(ndyn_max)
    phot_dat(region)%pmaer_av    = phot_dat(region)%pmaer_av    + float(ndyn)/float(ndyn_max) * phot_dat(region)%pmaer 
    phot_dat(region)%taus_aer_av = phot_dat(region)%taus_aer_av + float(ndyn)/float(ndyn_max) * phot_dat(region)%taus_aer 
    phot_dat(region)%taua_aer_av = phot_dat(region)%taua_aer_av + float(ndyn)/float(ndyn_max) * phot_dat(region)%taua_aer 

    deallocate(taus_aer)
    deallocate(taua_aer)
    deallocate(pmaer)

    Deallocate(aop_out_ext)
    Deallocate(aop_out_a  )
    Deallocate(aop_out_g  )

    status = 0

  END SUBROUTINE AEROSOL_INFO_M7
  !EOC
#endif

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    AEROSOL_INFO
  !
  ! !DESCRIPTION: assignment of aerosol optical depths
  ! 
  ! This is a crude method to provide some average values for the absorption and scattering
  ! terms by background aerosol choice of values defined according to the relative humidity.
  ! Absorption component can be set to zero throughout (M.van Weele, private comm.,2005).
  ! Scattering component chosen to be representative of background aerosol
  ! Moreover there is a choice as the whether the values defined by shettle and fenn are used
  ! This will require a look up table on 1x1,60 layers with indexes 1->4 with respect to
  ! location. At the moment background aerosol is chosen throughout
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE AEROSOL_INFO( region )
    !
    ! !USES:
    !
    use dims,         only : im, jm, lm, newsrun, ndyn, ndyn_max
    use binas,        only : xm_air, xm_h2o,grav
    use global_data,  only : mass_dat
    use MeteoData,    only : temper_dat, humid_dat, gph_dat, cc_dat, iwc_dat, lwc_dat, phlb_dat
    use MeteoData,    only : lsmask_dat
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in)       :: region
    !
    ! !REVISION HISTORY: 
    !      Jun 2005 - JEW - 
    !   26 Apr 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    real, dimension(:,:,:,:,:), allocatable  :: taus_aer, taua_aer
    real, dimension(:,:,:,:,:), allocatable  :: pmaer
    real, dimension(:,:,:),     allocatable  :: rhum, dens, part, dz, press_lay
    real, dimension(:,:,:),     pointer      :: q, phlb, temp, gph, frac, xland
    real                                     :: a_sc, b_sc, a_ab, b_ab, a_g, b_g
    real                                     :: bsa, baa, ga
    integer                                  :: i_type
    integer, dimension(:,:),    pointer      :: aero_clim

    real      :: wv, tr, scale_aero, lay1, lay2
    integer   :: i, j, l, k, kboun, i_ref, b, wav, ll, n 
    integer   :: i1, j1, i2, j2, lmr
    logical   :: aerosol, shettle_and_fenn

    real, dimension(8) :: rh_ref = (/0., 50., 70., 80., 90., 95., 98., 99./)

    real, dimension(4) :: pn_ref = (/ 15000., 4000., 20000., 5000./)
    !
    !     different aerosol types:                                          
    !        1 = rural aerosol                                              
    !        2 = maritime aerosol                                           
    !        3 = urban aerosol                                              
    !        4 = free troposphere aerosol               
    !-----------------------------------------------------------------------

    aerosol = .false.
    shettle_and_fenn = .true.

    call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
    lmr = lm(region)
    
    allocate(taus_aer(i1:i2, j1:j2, lmr, nbands_trop, ngrid))
    allocate(taua_aer(i1:i2, j1:j2, lmr, nbands_trop, ngrid))  
    allocate(pmaer   (i1:i2, j1:j2, lmr, nbands_trop, ngrid))
    allocate(rhum    (i1:i2, j1:j2, lmr))
    allocate(dens    (i1:i2, j1:j2, lmr))
    allocate(part    (i1:i2, j1:j2, lmr))
    allocate(dz      (i1:i2, j1:j2, lmr))
    allocate(press_lay(i1:i2, j1:j2, lmr))

    ! Initialize values

    taus_aer=0.
    taua_aer=0.
    pmaer   =0.
    
    ! read in met. data
    temp      => temper_dat(region)%data  ! (i1:i2, j1:j2, 1:lmr)
    q         =>  humid_dat(region)%data  ! (i1:i2, j1:j2, 1:lmr)
    phlb      =>   phlb_dat(region)%data  ! 
    gph       =>    gph_dat(region)%data  ! (i1:i2, j1:j2, 1:lmr+1)
    frac      =>     cc_dat(region)%data  ! (i1:i2, j1:j2, 1:lmr)
    xland     => lsmask_dat(region)%data  ! (i1:i2, j1:j2, 1)
    
    aero_clim =>   phot_dat(region)%aero_surface_clim  ! (i1:i2, j1:j2)


    ! initialize values

    scale_aero = 1.0

    ! the land-sea mask is used to ascribe either marine or rural aerosol for the bottom layers

    dz = 0. ; dens = 0. ; rhum = 0. 

    phot_dat(region)%taus_aer = 0.
    phot_dat(region)%taua_aer = 0.
    phot_dat(region)%pmaer = 0. 

    if (shettle_and_fenn) then

       if(newsrun) then
          do j=j1,j2 
             do i=i1,i2
                if(j<=10 .or. j>=80) then
                   aero_clim(i,j)=4
                else    
                   if(xland(i,j,1) <  30.) aero_clim(i,j)=2
                   if(xland(i,j,1) >= 30.) aero_clim(i,j)=1
                endif
             enddo
          enddo
       endif

       do l=1,lm(region)
          do j=j1,j2 
             do i=i1,i2
                dz(i,j,l) = (gph(i,j,l+1) - gph(i,j,l))
                press_lay(i,j,l) =  (phlb(i,j,l) + phlb(i,j,l+1)) * 0.01 * 0.5 ! hPa
                dens(i,j,l) = 7.2427e18 * press_lay(i,j,l)/temp(i,j,l)
                tr=1.-373.15/temp(i,j,l)
                wv=exp((((-.1299*tr-.6445)*tr-1.976)*tr+13.3185)*tr)  
                if(frac(i,j,l)<0.95) rhum(i,j,l)=q(i,j,l)*dens(i,j,l)*xm_air/xm_h2o*temp(i,j,l)/(1013.25*wv*7.24e16)
                ! JEW assume saturation when cloud fraction is very high.
                if(frac(i,j,l)>=0.95)  rhum(i,j,l)=98.0
                rhum(i,j,l)=min(98.,rhum(i,j,l))
             enddo
          enddo
       enddo

       !
       ! use land-sea mask to ascribe either marine or rural aerosol for different grid cells
       ! in the lower few KM
       !
       do l=1,lm(region)
          do j=j1,j2 
             do i=i1,i2
                if(l<5) then
                   i_type=aero_clim(i,j)
                elseif(l>=5) then
                   i_type=4
                endif
                kboun = 1
                lay1 = (phlb(i,j,l)/phlb(i,j,kboun))**3
                lay2 = (phlb(i,j,l+1)/phlb(i,j,kboun))**3
                if(i_type<4) then
                   part(i,j,l) = scale_aero*pn_ref(i_type)*dz(i,j,l)*100.
                   kboun = l
                else
                   part(i,j,l) = scale_aero*pn_ref(i_type)*0.5*(lay1+lay2)*dz(i,j,l)*100.
                endif

                i_ref = 8

                do k = 1,8
                   if(rh_ref(k) < rhum(i,j,l)) i_ref = k
                enddo

                do n=1,ngrid
                   do b=1,nbands_trop

                      if (n==1) wav=lmid(b)
                      if (n==2) wav=lmid_gridA(b) 

                      a_sc = (sca(wav,i_ref,i_type)-sca(wav,i_ref+1,i_type))/(rh_ref(i_ref)-rh_ref(i_ref+1))

                      b_sc = sca(wav,i_ref,i_type)- a_sc*rh_ref(i_ref)

                      a_ab = (abs_eff(wav,i_ref,i_type)-abs_eff(wav,i_ref+1,i_type))/(rh_ref(i_ref)-rh_ref(i_ref+1))

                      b_ab = abs_eff(wav,i_ref,i_type)- a_ab*rh_ref(i_ref)

                      a_g =(g(wav,i_ref,i_type)-g(wav,i_ref+1,i_type))/(rh_ref(i_ref)-rh_ref(i_ref+1))

                      b_g =g(wav,i_ref,i_type) - a_g*rh_ref(i_ref)           

                      bsa = a_sc*rhum(i,j,l) + b_sc
                      baa = a_ab*rhum(i,j,l) + b_ab
                      ga = a_g*rhum(i,j,l) + b_g

                      taus_aer(i,j,l,b,n) = bsa*part(i,j,l)
                      taua_aer(i,j,l,b,n) = baa*part(i,j,l)

                      if(taus_aer(i,j,l,n,1)>0.) then
                         ! do k = 1,nmom
                         pmaer(i,j,l,b,n)=ga
                         ! enddo
                      else
                         pmaer(i,j,l,b,n) = 0.
                      endif

                   enddo !nbands_trop
                enddo !ngrid

             enddo ! l
          enddo ! j
       enddo ! i

       phot_dat(region)%taus_aer = taus_aer
       phot_dat(region)%taua_aer = taua_aer
       phot_dat(region)%pmaer = pmaer 

    endif ! shettle and fenn switch

    ! JEW switch for the aerosol absorption and scattering properties  
    if (aerosol) then

       do l=1,lm(region) 
          do j=j1,j2 
             do i=i1,i2
                dens(i,j,l) = 7.2427e18 * press_lay(i,j,l)/temp(i,j,l)
                tr=1.-373.15/temp(i,j,l)
                wv=exp((((-.1299*tr-.6445)*tr-1.976)*tr+13.3185)*tr)  
                rhum(i,j,l)=q(i,j,l)*dens(i,j,l)*xm_air/xm_h2o*temp(i,j,l)/(1013.25*wv*7.24e16)
                if(rhum(i,j,l)>40. .and. rhum(i,j,l)<80.) pmaer(i,j,l,:,:) = 0.65
                if(rhum(i,j,l)>=80.)  pmaer(i,j,l,:,:) = 0.85
             enddo
          enddo
       enddo

       phot_dat(region)%taus_aer = 3.0e-3
       phot_dat(region)%taua_aer = 1.5e-4
       phot_dat(region)%pmaer = 0.7

    endif

    ! Averages
    phot_dat(region)%naer_av     = phot_dat(region)%naer_av     + (float(ndyn)/float(ndyn_max))
    phot_dat(region)%pmaer_av    = phot_dat(region)%pmaer_av    + (float(ndyn)/float(ndyn_max)) * phot_dat(region)%pmaer 
    phot_dat(region)%taus_aer_av = phot_dat(region)%taus_aer_av + (float(ndyn)/float(ndyn_max)) * phot_dat(region)%taus_aer 
    phot_dat(region)%taua_aer_av = phot_dat(region)%taua_aer_av + (float(ndyn)/float(ndyn_max)) * phot_dat(region)%taua_aer 
    
    ! Done
    deallocate(taus_aer)
    deallocate(taua_aer)
    deallocate(pmaer)
    deallocate(rhum)
    deallocate(dens)
    deallocate(part)
    deallocate(dz)
    deallocate(press_lay)

    nullify(q)
    nullify(temp)
    nullify(phlb)
    nullify(gph)
    nullify(frac)

    nullify(xland)
    nullify(aero_clim)

  END SUBROUTINE AEROSOL_INFO
  !EOC

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    SLINGO
  !
  ! !DESCRIPTION: A. Slingo's data for cloud particle radiative properties
  !               (from 'A GCM Parameterization for the Shortwave Properties of Water Clouds'
  !               JAS vol. 46 may 1989 pp 1419-1427)
  !
  !               Called everytime the meteo data is updated to calculate new
  !               cloud optical properties
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE SLINGO( region )                                                       
    !
    ! !USES:
    !
    use binas,         only : xmair, Avog
    use dims,          only : im, jm, lm, lmax_conv
    use global_data,   only : mass_dat
    use MeteoData,     only : gph_dat, lwc_dat, iwc_dat, cc_dat, phlb_dat, temper_dat, lsmask_dat
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in) :: region
    !
    ! !REVISION HISTORY: 
    !   26 Apr 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    real                               :: eff_rad ! effective radius no longer fixed but linked to LWP
    real                               :: rhodz, tau_c, xsa, press, airn, D_ge
    real                               :: rclf    ! inverse cloud fraction
    real                               :: clwc, ciwc ! [g/m3]
    real                               :: lfrac, sfrac ! scaled components due to land and sea fraction
    real,dimension(:,:,:),allocatable  :: taua_cld
    real,dimension(:,:,:),allocatable  :: taus_cld
    !total scattering optical depth for cloud layer (liquid+cirrus)
    !total absorption optical depth for cloud layer (liquid_cirrus)
    real,dimension(:,:,:),allocatable  :: pmcld !phase function (HG)

    !----------------------------Local------------------------------------------ 
    real,dimension(:,:,:),allocatable :: lwp !cloud liquid water path [g/m^2]
    real,dimension(:,:,:),pointer     :: frac, lwc, iwc, gph, phlb, temp, xland
        
    real, parameter  :: factor = 7.24e16*1.e6*xmair*29.2605/avog

    real,dimension(:,:,:), allocatable :: dz, totalwc, global_cloud_reff

    real, dimension(4)    :: abar, bbar, cbar, dbar, ebar, fbar
    ! A coefficient for extinction optical depth        
    ! B coefficiant for extinction optical depth        
    ! C coefficiant for single particle scat albedo     
    ! D coefficiant for single particle scat albedo     
    ! E coefficiant for asymmetry parameter             
    ! F coefficiant for asymmetry parameter             

    data abar/ 2.817e-02, 2.682e-02,2.264e-02,1.281e-02/ 
    data bbar/ 1.305    , 1.346    ,1.454    ,1.641    / 
    data cbar/-5.62e-08 ,-6.94e-06 ,4.64e-04 ,0.201    / 
    data dbar/ 1.63e-07 , 2.35e-05 ,1.24e-03 ,7.56e-03 / 
    data ebar/ 0.829    , 0.794    ,0.754    ,0.826    / 
    data fbar/ 2.482e-03, 4.226e-03,6.560e-03,4.353e-03/ 

    real   :: abari, bbari, cbari, dbari, ebari, fbari                                                        
    ! A coefficiant for current spectral interval       
    ! B coefficiant for current spectral interval       
    ! C coefficiant for current spectral interval       
    ! D coefficiant for current spectral interval       
    ! E coefficiant for current spectral interval       
    ! F coefficiant for current spectral interval       

    real    :: gc, wc, tot, tmp1 ,tmp2, tmp3
    !asymmetry factor                                    
    !single scattering albedo                            
    !total optical depth of cloud layer

    ! constants for scattering parameterization of Fu (1996)
    real, dimension(7) :: a0, a1

    data a0/-.236447E-03,-.236447E-03,-.266955E-03,-.266955E-03,-.266955E-03,-.258858E-03,.982244E-04/              
    data a1/.253817E+01 ,.253817E+01 ,.254719E+01 ,.254719E+01 ,.254719E+01 ,.253815E+01,.250875E+01/  

    ! Parameters for computing cloud effective radius according to Martin et al. (JAS 1994)
    real            :: denom,numerator
    real, parameter :: d_land=0.43
    real, parameter :: d_sea=0.33

    integer :: i,j,l,k, indxsl, n, i1, i2, j1, j2, lmr

    !----------- START----------

    call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
    lmr = lm(region)
    
    !-------------------------------------------------------------------------           
    !     Set index for cloud particle properties based on the wavelength,  
    !     according to A. Slingo (1989) equations 1-3:                      
    !     Use index 1 (0.25 to 0.69 micrometers) for visible                
    !     Use index 2 (0.69 - 1.19 micrometers) for near-infrared           
    !     Use index 3 (1.19 to 2.38 micrometers) for near-infrared          
    !     Use index 4 (2.38 to 4.00 micrometers) for near-infrared          

    indxsl = 1 

    !     Set cloud extinction optical depth, single scatter albedo,        
    !     asymmetry parameter, and forward scattered fraction:              

    abari = abar(indxsl)
    bbari = bbar(indxsl)
    cbari = cbar(indxsl)
    dbari = dbar(indxsl)
    ebari = ebar(indxsl)
    fbari = fbar(indxsl)
    !
    !--------------------------------------------------------------------------
    !     In the parameterization of Fu(1996) wavelength dependant extinction maybe
    !     calculated using a set of pre-defined constants:
    !     
    !      nm               a0                a1
    !    250-300         -.236447E-03      .253817E+01
    !    300-330         -.266955E-03      .254719E+01
    !    330-360         -.293599E-03      .254540E+01
    !    360-400         -.258858E-03      .253815E+01
    !    400-440         -.106451E-03      .252684E+01
    !    440-480          .129121E-03      .250410E+01
    !    480-520         -.954458E-04      .252061E+01
    !    520-570         -.303108E-04      .251805E+01
    !    570-640          .982244E-04      .250875E+01     
    !
    !    used in Beta=IWC(a0+a1/Dg)
    !--------------------------------------------------------------------------     
    allocate(taua_cld(i1:i2, j1:j2, lm(region)))
    allocate(taus_cld(i1:i2, j1:j2, lm(region)))
    allocate(pmcld   (i1:i2, j1:j2, lm(region))) 
    allocate(lwp     (i1:i2, j1:j2, lm(region)))

    allocate(dz               (i1:i2, j1:j2, lm(region)  ))
    allocate(totalwc          (i1:i2, j1:j2, lm(region)  ))
    allocate(global_cloud_reff(i1:i2, j1:j2, lm(region)  ))

    ! Initialize values

    taua_cld = 0. ; taus_cld = 0. ; pmcld = 0. ; lwp = 0.

    ! assume a baseline cloud radius, required for heterogeneous chemistry
    global_cloud_reff = 6.

    !JEW The ice and water particles are now treated seperately. For cloud the values are taken from slingo 
    !JEW the refractive index for ICE is very low below 750nm therefore T~T(scatt).

    iwc   => iwc_dat   (region)%data  ! (i1:i2, j1:j2, 1:lmr)
    frac  => cc_dat    (region)%data  ! (i1:i2, j1:j2, 1:lmr)
    gph   => gph_dat   (region)%data  ! (i1:i2, j1:j2, 1:lmr+1)
    lwc   => lwc_dat   (region)%data  ! (i1:i2, j1:j2, 1:lmr)
    phlb  => phlb_dat  (region)%data  ! 
    temp  => temper_dat(region)%data  ! (i1:i2, j1:j2, 1:lmr)
    xland => lsmask_dat(region)%data  ! (i1:i2, j1:j2, 1)

    ! No negative input
    lwc=max(0.,lwc)
    iwc=max(0.,iwc)  

    ! read in new cloud data to feed into the slingo routine. The values of lwc are zero in top levels so limit layer loop
   
    do l=1,lmax_conv
       do j=j1,j2 
          do i=i1,i2
             press = (phlb(i,j,l) + phlb(i,j,l+1)) * 0.5 ! Pa
             dz(i,j,l) = ( gph(i,j,l+1) - gph(i,j,l) )

             ! We have replaced the parameterization of McFarlane et al. (1992) with that of Martin et al. (1994).
             ! In the IFS a crude filter of 0.5 for the land fraction is used with the CNN(Marine) = 40.
             ! and CNN(Land) = 900. Here we weight the final CCN with the actual land fraction so as to introduce
             ! more variability. 

             ! JEW : there is a potential problem in that nonzero cloud fractions may occur with no associated lwc value
             ! on TM5 vertical resolutions, therefore a filter w.r.t. both fraction and cloud liquid path are included. 
             if( lwc(i,j,l) > 1.e-10 .and. frac(i,j,l) > 0.02 ) then
                ! JEW calculate total water path locally : convert to g/m(2) for slingo input
                ! following the conversion procedure for LWC from ECMWF input from old cloud subroutine.

                ! Included comments from old code to explain the prefactor in rhodz:
                ! rho  = airn*1e6*xmair/avo                   ! g/m3
                ! dz   = 29.2605*temp(i,j,l)* alog(phlb(i,j,l)/(1.0+phlb(i,j,l+1)))
                rclf=1./frac(i,j,l)
                rhodz = factor*press*alog(phlb(i,j,l)/(1.0+phlb(i,j,l+1)))

                ! VH - scale lwc and lwp with cloud fraction, to compute cloud optical properties
                ! and droplet radius representative for cloudy part only
                lwp(i,j,l) = rhodz*lwc(i,j,l)*rclf

                airn=7.24e16*press/temp(i,j,l) !#/cm3
                clwc=lwc(i,j,l)*xmair*airn*1.e6/avog ! g/m3

                ! Effective radius: Martin et al. (JAS 1994) parametrization
                !if (xland(i,j,l) > 50.) then
                ! Above land use ccn of ~900
                ! D_land = 0.43
                ! CCNLND = 900
                ! NTOT=-2.10E-04*CCNLAND*CCNLAND+0.568*CCNLAND-27.9
                ! DENOM=4.0*pi*rho_w*NTOT*(1.0+D_land*D_land)**3 
                ! with rho_w in g/m3.
                denom = 6547.52*1.e6
                numerator=3.0*clwc*rclf*(1.0+3.0*D_land*D_land)**2
                lfrac=0.
                if((numerator/denom) > 1.e-20) lfrac=1.e4*exp(0.333*LOG(numerator/denom))
                !else
                ! Maritime air mass
                ! D_sea = 0.333
                ! CCNSEA = 40
                ! NTOT=-1.15E-03*CCNSEA*CCNSEA+0.963*CCNSEA+5.30
                ! DENOM=4.0*pi*rho_w*NTOT*(1.0+D_sea*D_sea)**3
                denom = 723.210*1.e6
                numerator=3.0*clwc*rclf*(1.0+3.0*D_sea*D_sea)**2
                sfrac=0.
                if((numerator/denom) > 1.e-20) sfrac=1.e4*exp(0.333*LOG(numerator/denom))
                !endif

                ! TvN: Is this the best way to average land and sea?
                eff_rad=(xland(i,j,1)/100.*lfrac)+(1.0-xland(i,j,1)/100.)*sfrac

                ! prevent the radius of non-precipitation clouds being too big
                ! these size limits are equal to those chosen in the IFS
                eff_rad=min(16.0,max(eff_rad, 4.0))

                tmp1 = abari + bbari/eff_rad
                tmp2 = 1. - cbari - dbari*eff_rad
                tmp3 = fbari*eff_rad

                !     Do not let single scatter albedo be 1; delta-eddington solution
                !     for non-conservative case:
                wc   = min(tmp2,.999999)               
                tot  = lwp(i,j,l)*tmp1      
                gc   = ebari + tmp3 
                ! JEW : no wavelength dependence for the absorption or scattering effects due to liquid clouds !!!!!
                taua_cld(i,j,l) = (1.-wc)*tot 
                taus_cld(i,j,l) = wc*tot
                ! avoid possible negatives due to input data            
                taua_cld(i,j,l)=max(0.0,taua_cld(i,j,l))

                global_cloud_reff(i,j,l) = eff_rad

                ! JEW : for calculating the scattering component due to ice 
                if(iwc(i,j,l) > 1.e-10) then
                   airn=7.24e16*press/temp(i,j,l)
                   ! iwc in g/m3 from TM5 definition       
                   ciwc=iwc(i,j,l)*xmair*airn*1.e6/avog
                   ! Following Eq. (5) of Heymsfield and McFarquhar (JAS, 1996), 
                   ! the cross-sectional surface area A (km^-1) 
                   ! can be approximated by:
                   ! 10*IWC^0.9, where IWC in g/m3.
                   ! Thus, A in m^2/m^3 = m^-1 is given by 0.01 IWC^0.9,
                   ! which implies that xsa is in cm^-1.
                   xsa=1.0e-4*ciwc**0.9
                   !
                   ! calculate D_ge using the relationship in Fu (1996) where Beta=extinction co-efficient (m-1)
                   !
                   !  D_ge = 2(3)**0.5/(3 Rho)*(IWC/xsa)
                   ! 
                   ! The above relationship is for instance given in Table 1
                   ! in McFarquhar and Heymsfield (JAS, 1997).
                   ! Below an ice density in units g/cm^3 and
                   ! IWC in g/m^3 are used.
                   ! The conversion of IWC from g/m^3 to g/cm^3
                   ! gives a factor 10^6, which together with
                   ! the division by 100 converts from cm to um.
                   !
                   D_ge=(2.*1.73205/(3.*0.917))*(ciwc/xsa)
                   ! convert to uM
                   D_ge=D_ge/100.
                   !
                   ! Cirrus scattering has a wavelength dependancy
                   !
                   taus_cld(i,j,l)=taus_cld(i,j,l)+((ciwc*(a0(3)+(a1(3)/D_ge)))*dz(i,j,l))        
                endif

                if (taus_cld(i,j,l) > 0.) then 
                   pmcld(i,j,l)=gc 
                else 
                   pmcld(i,j,l)=0. 
                end if
             end if
          enddo
       enddo
    enddo

    ! Store optical depths and phase functions
    phot_dat(region)%pmcld      = pmcld
    phot_dat(region)%taus_cld   = taus_cld  
    phot_dat(region)%taua_cld   = taua_cld
    phot_dat(region)%cloud_reff = global_cloud_reff

    ! Averages
    phot_dat(region)%lwp_av      = lwp 
    phot_dat(region)%cfr_av      = phot_dat(region)%cfr_av      + frac
    phot_dat(region)%reff_av     = global_cloud_reff
    phot_dat(region)%ncloud_av   = phot_dat(region)%ncloud_av   + 1
    phot_dat(region)%pmcld_av    = phot_dat(region)%pmcld_av    + pmcld 
    phot_dat(region)%taus_cld_av = phot_dat(region)%taus_cld_av + taus_cld 
    phot_dat(region)%taua_cld_av = phot_dat(region)%taua_cld_av + taua_cld 

    nullify(lwc)
    nullify(frac)
    nullify(iwc)
    nullify(gph)
    nullify(phlb)
    nullify(temp,xland)

    deallocate(taua_cld)
    deallocate(taus_cld)
    deallocate(pmcld)
    deallocate(lwp)

    deallocate(dz)
    deallocate(totalwc)
    deallocate(global_cloud_reff)

  END SUBROUTINE SLINGO
  !EOC

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    UPDATE_CSQY
  !
  ! !DESCRIPTION: 
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE UPDATE_CSQY( region )
    !
    ! !USES:
    !
    use dims
    use binas,           only: Avog, xmair, grav
    use global_data,     only: mass_dat
    use MeteoData,       only: phlb_dat, temper_dat, m_dat
    use chem_param,      only: xmo3, fscale, iacet
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in)                    :: region   
    !
    ! !REVISION HISTORY: 
    !   26 Apr 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    integer                                :: i,j,l 
    real,dimension(:,:,:),pointer          :: temperature   
    real,dimension(:,:,:),pointer          :: phlb
    real,dimension(:,:,:),pointer          :: mass
    real,dimension(:,:,:,:),pointer        :: qyacet    
    real,dimension(:,:,:),allocatable      :: density
    real,dimension(:,:,:),allocatable      :: pressure

    integer                      :: k, m, table_pos, i1, j1, i2, j2, lmr
    real                         :: xa, xb, te, chix, ww, temper, ptorr
    real                         :: phi,  qy, tt, alpha, delta_t
    real,dimension(maxwav)       :: rd, phi0
    real                         :: a0, b0, a1, b1, a2, b2, a3, b3, c3, a4, b4
    real                         :: term,term1,term2,t_scale            
    real                         :: airn,aird 
    
    integer,parameter            :: n_ind =34 ! number of increments in the look-up table
    real,dimension(n_ind)        :: temp_ind       
    
    phlb        => phlb_dat(region)%data
    temperature => temper_dat(region)%data
    qyacet      => phot_dat(region)%qy_c2o3
    mass        => m_dat(region)%data
    
    call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
    lmr = lm(region)
    
    allocate(density (i1:i2, j1:j2, lmr))
    allocate(pressure(i1:i2, j1:j2, lmr))

    !---------------------------------------------------------------------------------   
    ! Only update the temperature sensitive regions of the spectral
    ! grids. That is, initialize values values to either zero or cs_ values for selected
    ! species.                                  
    !--------------------------------------------------------------------------------- 

    do k  = 1,lm(region)
       do j  = j1,j2
          do i  = i1,i2
             ! define air pressure
             pressure(i,j,k) = (phlb(i,j,k) + phlb(i,j,k+1))/2
          enddo
       enddo
    enddo

    ! define air density
    density = 7.24e16*pressure/temperature(i1:i2, j1:j2, 1:lmr) 

    ! define temperature index array from the lookup table
    do i = 1, 34
       temp_ind(i) = 182.5 + (i-1) * 5.0
    enddo


    !---------------------------------------------------------------------
    !        QUANTUM YIELD OF METHYGLYOXAL S. KOCH and G. K. MOORTGAT       
    !        J Phys Chem, 102, 9142-9153, 1998.
    !
    ! JEW: the qy_ch3cocho array has been reduced to 52 bins to represent the pressure.
    !      dep. spectral bins ONLY !!   
    !---------------------------------------------------------------------

    ! Calculate co-efficients for METHYGLYOXAL qy outside loop
    phi0 = 1. ; rd = 0.      
    ! for wave < 380nm qy is essentially = 1.0.

    do l = 1,39
       if(l<32) then
          phi0(l) = 1
       elseif(l>=32) then
          phi0(l) = 8.15e-9 * exp(7131./wave(l+37)*1.e-7)
       endif
       rd(l)   = 7.34e-9 * exp(8793./wave(l+37)*1.e-7)
    enddo

    do l = 40,52
       phi0(l) = 3.63e-7 * exp(5693./wave(l+37)*1.e-7) 
       rd(l)   = 1.93e4*exp(-5639./wave(l+37)*1.e-7)
    enddo

    do k  = 1,lm(region) 
       do j = j1,j2
          do i = i1,i2

             !        QUANTUM YIELD OF METHYGLYOXAL JPL 2006 P4-71       
             !        CH3COCHO -> CH3C(O)O2 + HO2 + CO     (1)
             !                 -> CH4 + 2CO                (2)
             !                 -> CH3CHO + CO              (3) 
             ! the predominant products are from channel(1) for wav 240-480nm                                    

             ! Pa -> Torr          
             !ptorr= (pressure(i,j,k)/100.)*760./1.013*1e-3
             ptorr= (pressure(i,j,k))*0.0075006
             !second absorption band     
             do l = 1,39 
                qy   = (phi0(l) * rd(l))/(rd(l) + ptorr*phi0(l)) 
                phot_dat(region)%qy_ch3cocho(i,j,k,l) = min(1.0,qy)
             end do
             ! switch to the formulation by Chen et al, JPC, 104, 11126-11131, 2000 for wav > 420nm
             do l = 40,52
                qy   = phi0(l)/(1.+(phi0(l)*rd(l)*ptorr))
                phot_dat(region)%qy_ch3cocho(i,j,k,l) = min(1.0,qy)
             enddo
             !
             ! calculate the second photolysis channel for acetone
             !
             do l=26,35
                table_pos=int((temperature(i,j,k)-(temp_ind(1)-0.0*5))/5)+1
                table_pos=min(max(1,table_pos),34)  ! bug fix for temperatures below 175.5
                qy=(1-qy_co_look(l,table_pos))/(1.0+a1_acet(l,table_pos)*density(i,j,k))
                qyacet(i,j,k,l)=max(0.0,qy)   
             enddo
             do l=36,89
                ! determine constants for calculating qy
                table_pos=int((temperature(i,j,k)-(temp_ind(1)-0.0*5))/5)+1
                table_pos=min(max(1,table_pos),34)  ! bug fix for temperatures below 175.5
                a1=1.0+(density(i,j,k)*a4_acet(l,table_pos))+a3_acet(l,table_pos)
                a2=1.0+(density(i,j,k)*a2_acet(l,table_pos))+a3_acet(l,table_pos)
                a4=1.0+(density(i,j,k)*a4_acet(l,table_pos))
                qy=(1-qy_co_look(l,table_pos))*(a1/(a2*a4))
                qyacet(i,j,k,l)=max(0.0,qy)     
             enddo
          end do  ! longitude
       end do ! latitude
    end do ! level

    deallocate(density)
    deallocate(pressure)
    nullify(temperature)
    nullify(mass)    
    nullify(phlb)
    nullify(qyacet)
    
  END SUBROUTINE UPDATE_CSQY
  !EOC


  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    PIFM
  !
  ! !DESCRIPTION: 
  !                                                                      *
  !            PRACTICAL IMPROVED FLUX METHOD (PIFM)                     *
  !                 to calculate actinic fluxes                          *
  !     Zdunkowski,Welch,Korb: Beitr. Phys. Atmosph. vol. 53, p. 147 ff  *
  !                                                                      *
  !     This version is not suitable for calculation for conserving      *
  !     scattering (W0=1). W0 is limited to W0 <= 1. - 1.E-15.           *
  !     For W0 = 1, AL(4) and AL(5) has to be calculated differently.    *
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE PIFM(region, zangle, alb, cst_o3_col, dv2, dv3, taua_aer_col, taus_aer_col, paer_col, fact)
    !
    ! !USES:
    !
    use dims,  only : lm
    use binas, only : pi
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in) :: region
    real,    intent(in) :: zangle    ! zenith angle
    real,    intent(in) :: alb       ! albedo 

    real, dimension(lm(region),maxwav)  :: cst_o3_col         ! temp dep o3 cross sections
    real, dimension(lm(region))         :: dv2, dv3             ! differential column info
    real, dimension(lm(region),nbands_trop,ngrid) :: taua_aer_col, taus_aer_col   ! optical depth aerosols     
    real, dimension(lm(region),nbands_trop,ngrid) :: paer_col
    real, dimension(lm(region),nbands_trop) :: fact             !actinic flux 
    !
    ! !REVISION HISTORY: 
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    real, dimension(3*(lm(region)+1))   :: rw,  & !flux array for cloudy sky
                                           rf     !flux array for clear sky 
    real, dimension(lm(region))     :: tu1,  &   !parallel solar flux   
                                       tu2       !matrix coefficient 

    real, dimension(lm(region),5)     :: al
    real, dimension(lm(region)+1,nbands_trop):: sd, fd, fu
    real, dimension(0:nmom)         :: pray  ! phase functions
    real                            :: taus, taua, tautot, g
    real, dimension(lm(region),nbands_trop)  :: taua_clr, taus_clr  ! optical depth clear sky    

    !     diffusivity factor                                                
    real, parameter ::  u  = 2., delu0 = 1.e-3, resonc = 1.e-6
    integer             :: grid, l, k, n, nl, k3,  maxlev,  maxlay2, maxlev3       
    real                        :: p1, w0, f, b0, bu0                              
    real                        :: eps, factor, ueps2, smooth1, smooth2    
    real                        :: alph1, alph2, alph3, alph4                              
    real                        :: gam1, gam2, e, rm, tds1, td1, td2               
    real                        :: fact_bot, fact_top, arg                                         
    !downward diffuse flux            
    !upward diffuse flux 
    real                        :: a, b, c, gamma, u0
    real                        :: cs_o2

    !     internal integer variable                                         
    maxlev  = lm(region) + 1     
    maxlay2 = 2 * lm(region)     
    maxlev3 = 3 * maxlev

    ! intitialise arrays
    al = 0. ; fd = 0. ; sd = 0. ; fu = 0. ; tu1 = 0. ; tu2 = 0. ; rw = 0. ; rf = 0.

    !initialise output (actinic flux)
    fact = 0.

    !-----correction of the air mass factor---------------------------------  

    !   F. Kasten and T. Young, Revised optical air mass tabels and
    !   approximation formula (1989) Aplied Optics Vol 28, No. 22 P. 4735   
    !   and J. Lenoble, atmospheric radiative transfer (1993), P. 236

    a = 0.50572 ; b = 6.07995 ; c = 1.63640

    ! define air mass factor in mu
    gamma = 90. - zangle
    u0 = sin(gamma*pi/180.) + a *(gamma+b)**(-c)
    u0 = min(1.,u0)

    !===================================================================    
    !     calculation of the matrix coefficients a1,...,a5                  
    !=================================================================== 

    ! determine phase functions
    pray(0) = 1. ; pray(1) = 0. ; pray(2)=0.1 ; pray(3:nmom) = 0. 

    ! reverse order for input parameters

    dv2(1:lm(region)) = dv2(lm(region):1:-1)
    dv3(1:lm(region)) = dv3(lm(region):1:-1)

    ! do not calculate for band #1  
    do l  = 1,nbands_trop                                                           
       if (zangle <= 71.) then
          nl = lmid(l)
          grid = 1
          cs_o2 = 7.322e-24
       elseif (zangle > 71. .and. zangle<=sza_limit) then
          nl = lmid_gridA(l)
          grid = 2
          cs_o2 = 6.608e-24
       endif

       ! reverse order for input parameters
       cst_o3_col(1:lm(region),nl) = cst_o3_col(lm(region):1:-1,nl)
       taus_aer_col(1:lm(region),l,grid) = taus_aer_col(lm(region):1:-1,l,grid)
       taua_aer_col(1:lm(region),l,grid) = taua_aer_col(lm(region):1:-1,l,grid)
       paer_col(1:lm(region),l,grid) = paer_col(lm(region):1:-1,l,grid)

       do k  = 1,lm(region)

          ! Calculate optical depth (clear-sky)
          if(nl<18) then 
             taua_clr(k,l) = cs_o2*dv2(k) + cst_o3_col(k,nl)*dv3(k)
          else
             taua_clr(k,l) = cst_o3_col(k,nl)*dv3(k)
          endif
          taus_clr(k,l) = cs_ray(nl)*1./0.2095*dv2(k)

          taus = taus_clr(k,l) + taus_aer_col(k,l,grid)
          taua = taua_clr(k,l) + taua_aer_col(k,l,grid) 

          tautot = taus + taua

          g = 0.
          if (taus > 0.) &
               g = (paer_col(k,l,grid)* taus_aer_col(k,l,grid) + pray(1)* taus_clr(k,l) )/taus

          if (tautot .ne. 0.) then 
             w0=taus / tautot 
          else 
             w0=0. 
          end if

          w0 = min(w0,1.-1.e-15)

          !      P1: first expansion coefficient of the phase function    

          p1=3.*g 

          !      F: fraction of radiation contained in diffraction peak    
          f=g**2 

          !      B0:  fractional mean backward scattering coefficient    
          !           of diffuse light                             
          !      BU0: backward scattering coefficient of primary scattered   
          !           parallel solar light                         
          !      for small P1 SMOOTH1,SMOOTH2 manage the smooth change of B0 
          !      BU0 to 0                                          
          if (p1 <= 0.1) then 
             smooth1=1.33333333-p1*3.3333333 
             smooth2=10.*p1 
          else 
             smooth1=1. 
             smooth2=1. 
          end if

          b0=(3.-p1)/8.  *smooth1 
          bu0=0.5-u0/4.*(p1-3.*f)/(1.-f)  *smooth2 

          !      alpha coefficient                                 
          alph1=u*(1.-(1.-b0)*w0)
          alph2=u*b0*w0
          alph3=w0*bu0*(1-f)
          alph4=w0*(1.-bu0)*(1-f)

          !      epsilon and gamma coefficient                     
          eps=sqrt(alph1**2-alph2**2)

          factor=1.-w0*f 

          !      check for resonance condition in GAM1 and GAM2, if fulfil th
          !      chance U0(J) and calculate UEPS2, BU0, ALPH3, ALPH4 again.  

          ueps2=(u0 *eps)**2
          arg = ueps2-factor**2

          if (arg < 0.) arg = -1. * arg

          if (arg < resonc) then
             if (ueps2.lt.factor**2) then
                u0 = u0 - delu0
             else
                u0 = u0 + delu0
             end if
             ueps2=(u0 * eps)**2
             bu0=0.5-u0/4.*(p1-3.*f)/(1.-f)  *smooth2
             alph3=w0*bu0*(1-f)
             alph4=w0*(1.-bu0)*(1-f)
          end if

          gam1=( factor*alph3-u0 * (alph1*alph3+alph2*alph4) ) * &
               1/(factor**2-ueps2)
          gam2=(-factor*alph4-u0 * (alph1*alph4+alph2*alph3) ) * &
               1/(factor**2-ueps2)

          e=exp(-eps*tautot)
          rm=alph2/(alph1+eps)

          al(k,4)=e*(1.-rm**2.)/(1.-e**2. * rm**2.)
          al(k,5)=rm*(1.-e**2.)/(1.-e**2. * rm**2.)
          al(k,1)=exp(-factor*tautot/u0)
          al(k,2)=-al(k,4)*gam2-al(k,5)*gam1*al(k,1) + gam2*al(k,1)
          al(k,3)=-al(k,5)*gam2-al(k,4)*gam1*al(k,1) + gam1
       enddo

       !====================================================================   
       ! matrix inversion                                                      
       !====================================================================   

       !        direct solution of the first four equations                    
       rf(1) = u0 * flux(nl) 
       rf(2) = 0.

       !       5th to 10th equation: bring matrix elements on the left of the m
       !       diagonal to the rhs:  save elements on the right of the main    
       !                             diagonal in array -tu(l,1)                
       rf(3) = al(1,3) * rf(1) 
       rf(4) = al(1,1) * rf(1) 
       rf(5) = al(1,2) * rf(1) 

       tu1(1) = al(1,4) 
       tu2(1) = al(1,5)

       ! blocks of 6 equations: eliminate left matrix elements, save righ
       !                              matrix elements in array -tu(l,i),       
       !                              calculate rhs.                           
       do k=2,lm(region)
          k3=3*k
          td1 = 1./(1.-al(k,5)*tu2(k-1))
          td2 = al(k,4)*tu2(k-1)
          tu1(k) = td1*al(k,4)
          tu2(k) = al(k,5) + td2*tu1(k)
          rf(k3) = td1 * (al(k,3)*rf(k3-2) + al(k,5)*rf(k3-1))
          rf(k3+1)= al(k,1)*rf(k3-2)
          rf(k3+2)= al(k,2)*rf(k3-2) + al(k,4)*rf(k3-1)+td2*rf(k3)
       end do

       !    last two equations: the same as before                         
       tds1       = 1. / (1.-alb*tu2(lm(region)))
       rf(maxlev3) = tds1 * (alb * rf(maxlev3-2)+   &
            alb * rf(maxlev3-1))

       !        now we have created an upper triangular matrix the elements of 
       !        are -tu(l,i), 0, or 1 (in the main diagonal). the 0 and 1 eleme
       !        are not stored in an array. let us solve the system now and sto
       !        results in the arrays rf (fluxes clear sky) and rw (fluxes clou

       do k=lm(region),1,-1
          k3=3*k

          rf(k3+2) = rf(k3+2) + tu2(k)*rf(k3+3)  
          rf(k3) = rf(k3) + tu1(k)*rf(k3+3)    

          sd(k+1,l)  = rf(k3+1)                                    
          fd(k+1,l)  = rf(k3+2)                                    
          fu(k+1,l)  = rf(k3+3)                                    
       end do

       sd(1,l)  = rf(1)    
       fd(1,l)  = rf(2)    
       fu(1,l)  = rf(3)     

       !        calculate the actinic flux                                     

       fact_top = sd(1,l)/u0 + u * fd(1,l)   + u * fu(1,l)

       do k = 1,lm(region)

          fact_bot = sd(k+1,l)/u0 +     &                
               u * fd(k+1,l) + u * fu(k+1,l)                                             
          fact(k,l) = max(0. ,(fact_top + fact_bot)/2.)
          fact_top = fact_bot
       end do

       ! swap vertical levels to the default order of the model
       fact(1:lm(region),l) = fact(lm(region):1:-1,l)
       cst_o3_col(1:lm(region),nl) = cst_o3_col(lm(region):1:-1,nl)

    enddo    ! spectral bands (nbands)

  END SUBROUTINE PIFM
  !EOC

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:   PIFM_RAN
  !
  ! !DESCRIPTION: Pifm method including random overlap method for clouds
  ! 
  !************************************************************************
  !*            PRACTICAL IMPROVED FLUX METHOD (PIFM)                     * 
  !*                 to calculate actinic fluxes                          *
  !*     Zdunkowski,Welch,Korb: Beitr. Phys. Atmosph. vol. 53, p. 147 ff  *
  !*                                                                      *
  !*           Cloud effects added using the method of :                  *
  !*     Geleyn and Hollingworth, Contribs. Atms.Phys,52(1),1979          *
  !*                                                                      *
  !************************************************************************      
  !*     This version is not suitable for calculation for conserving      *
  !*     scattering (W0=1). W0 is limited to W0 .le. 1. - 1.E-15.         *
  !*     For W0 = 1, AL(4) and AL(5) has to be calculated differently.    *
  !************************************************************************
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE PIFM_RAN(region, zangle, alb, cst_o3_col, dv2, dv3,       &
                      taua_cld_col, taus_cld_col, pcld_col,            &
                      taua_aer_col, taus_aer_col, paer_col, fact, frac )
    !
    ! !USES:
    !
    use dims,  only : lm
    use binas, only : pi
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in)               :: region
    real,    intent(in)               :: zangle     ! zenith angle
    real,    intent(in)               :: alb        ! albedo
    
    real,dimension(lm(region))        :: frac       ! cloud fraction per layer (0->1)
    real,dimension(lm(region),maxwav) :: cst_o3_col ! o3 cross sections
    real,dimension(lm(region))        :: dv2, dv3   ! differential column info

    real,dimension(lm(region))                   :: taua_cld_col, taus_cld_col ! optical depth clouds              
    real,dimension(lm(region),nbands_trop)       :: taua_clr_col, taus_clr_col ! optical depth clear sky
    real,dimension(lm(region),nbands_trop,ngrid) :: taua_aer_col, taus_aer_col ! optical depth aerosols   
    real,dimension(lm(region),nbands_trop)       :: fact     ! actinic flux 
    real,dimension(lm(region),nbands_trop,ngrid) :: paer_col ! aerosol phase functions
    real,dimension(lm(region))                   :: pcld_col ! cloud phase functions
    real,dimension(0:nmom)                       :: pray     ! rayleigh phase function
    !
    ! !REVISION HISTORY: 
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    real,dimension(3*(lm(region)+1)) :: rw,  & ! flux array for cloudy sky
                                        rf     ! flux array for clear sky 
    real,dimension(lm(region)) :: tu1, & ! parallel solar flux   
                                  tu2    ! matrix coefficient 

    real,dimension(lm(region),5) :: al
    real,dimension(lm(region)+1,nbands_trop):: sd, fd, fu
    real,dimension(lm(region),nbands_trop)  :: TS_PI_CLR,TA_PI_CLR, G_PI_CLR, TS_PI_CLD
    real,dimension(lm(region))              :: TA_PI_CLD, G_PI_CLD

    real      ::  U,DELU0,RESONC,a,b,c,gamma,u0,cs_o2 

    integer   :: grid,j,k,l,maxlev,maxlay2,maxlev3,nl,k3 

    real :: w0,p1,F,smooth1,smooth2,b0,bu0,alph1,alph2,alph3,alph4,tautot,eps,factor
    real :: rm,gam1,gam2,e,tauscat,td1,td2,tds1,ueps2,g,arg,fact_bot, fact_top

    !     diffusivity factor
    DATA   U / 2./

    DATA    DELU0 /1.E-3/ 

    DATA    RESONC /1.E-6/

    real    :: AL_CLR_1,AL_CLR_2,AL_CLR_3,AL_CLR_4,AL_CLR_5   !matrix coefficient for clear sky
    real    :: AL_CLD_1,AL_CLD_2,AL_CLD_3,AL_CLD_4,AL_CLD_5   !matrix coefficient for cloudy sky


    !-----correction of the air mass factor---------------------------------
    !   F. Kasten and T. Young, Revised optical air mass tables and               
    !   approximation formula (1989) Aplied Optics Vol 28, No. 22 P. 4735   
    !   and J. Lenoble, atmospheric radiative transfer (1993), P. 236     

    a = 0.50572 ; b = 6.07995 ; c = 1.63640

    ! define air mass factor in mu
    gamma = 90. - zangle                                                                         
    u0 = sin(gamma*pi/180.) + a *(gamma+b)**(-c)         
    u0 = min(1.,u0)    

    !---------------------------------------------------------------------     
    !     internal integer variable 

    MAXLEV  = lm(region) + 1
    MAXLAY2 = 2 * lm(region)
    MAXLEV3 = 3 * MAXLEV

    ! initialize

    fact = 0. ; sd = 0 ; fd = 0. ;  fu = 0. ; td1 = 0.

    rf = 0. ; rw = 0. ; al = 0. ;   tu1 = 0. ; tu2 = 0.

    ! determine phase functions
    pray(0) = 1. ; pray(1) = 0. ; pray(2)=0.1 ; pray(3:nmom) = 0. 

    dv2(1:lm(region)) = dv2(lm(region):1:-1)
    dv3(1:lm(region)) = dv3(lm(region):1:-1)
    frac(1:lm(region)) = frac(lm(region):1:-1)

    taua_cld_col(1:lm(region)) = taua_cld_col(lm(region):1:-1)

    taus_cld_col(1:lm(region)) = taus_cld_col(lm(region):1:-1)

    pcld_col(1:lm(region)) = pcld_col(lm(region):1:-1)

    do l  = 1,nbands_trop 

       if (zangle <= 71.) then
          nl = lmid(l)
          grid = 1
          cs_o2 = 7.322e-24
       elseif (zangle > 71. .and. zangle<=sza_limit) then
          nl = lmid_gridA(l)
          grid = 2
          cs_o2 = 6.608e-24
       endif

       ! reverse order for input parameters
       cst_o3_col(1:lm(region),nl) = cst_o3_col(lm(region):1:-1,nl)
       taus_aer_col(1:lm(region),l,grid) = taus_aer_col(lm(region):1:-1,l,grid)
       taua_aer_col(1:lm(region),l,grid) = taua_aer_col(lm(region):1:-1,l,grid)
       paer_col(1:lm(region),l,grid) = paer_col(lm(region):1:-1,l,grid)

       ! fill array for absorption and scattering components before performing
       ! calculations.   
       do K = 1,lm(region)

          taus_clr_col(k,l) = cs_ray(nl)*1./0.2095*dv2(k)

          if(nl<18) then
             taua_clr_col(k,l) = cs_o2*dv2(k) + cst_o3_col(k,nl)*dv3(k)
          else
             taua_clr_col(k,l) = cst_o3_col(k,nl)*dv3(k)
          endif

          TS_PI_CLR(K,L) = TAUS_CLR_col(K,L)+TAUS_AER_col(K,L,grid)
          TA_PI_CLR(K,L) = TAUA_CLR_col(K,L)+TAUA_AER_col(K,L,grid)
          TS_PI_CLD(K,L) = TAUS_CLD_col(K)
          TA_PI_CLD(K) = TAUA_CLD_col(K)

          IF (TAUS_CLR_col(K,L)+TAUS_AER_col(K,L,grid)>0.) THEN
             G_PI_CLR(K,L)  = (PRAY(1)*TAUS_CLR_col(K,L) +   &
                  PAER_col(k,l,grid)*TAUS_AER_col(K,L,grid))/  &
                  (TAUS_CLR_col(K,L)+TAUS_AER_col(K,L,grid))                
          ELSE
             G_PI_CLR(K,L)  = 0.                 

          ENDIF
          G_PI_CLD(K)  = PCLD_col(k) 

       enddo

       do K = 1,lm(region)       

          !*****  first: clear sky *******************************************

          TAUTOT = TS_PI_CLR(K,L)+TA_PI_CLR(K,L)


          if (tautot /= 0.) then  
             W0=TS_PI_CLR(K,L) / TAUTOT
          ELSE
             W0=0.
          ENDIF

          W0 = MIN(W0,1.-1e-15)

          !           P1: first expansion coefficient of the phase function

          P1=3.*G_PI_CLR(K,L)                            

          !          F: fraction of radiation contained in diffraction peak

          F=G_PI_CLR(K,L)**2                        

          !           B0:  fractional mean backward scattering coefficient of diffuse light
          !           BU0: backward scattering coefficient of primary scattered parallel solar light

          !           for small P1 SMOOTH1,SMOOTH2 manage the smooth change of B0 and
          !           BU0 to 0

          IF (P1<=0.1) THEN
             SMOOTH1=1.33333333-P1*3.3333333
             SMOOTH2=10.*P1
          ELSE
             SMOOTH1=1
             SMOOTH2=1
          ENDIF

          B0=(3.-P1)/8.  *SMOOTH1                                 
          BU0=0.5-U0/4.*(P1-3.*F)/(1.-F)  *SMOOTH2    

          !           alpha coefficient

          ALPH1=U*(1.-(1.-B0)*W0)     
          ALPH2=U*B0*W0               
          ALPH3=W0*BU0*(1-F)
          ALPH4=W0*(1.-BU0)*(1-F)

          !           epsilon and gamma coefficient

          EPS=SQRT(ALPH1**2-ALPH2**2)          

          FACTOR=1.-W0*F

          !           check for resonance condition in GAM1 and GAM2, if fulfil then
          !           chance U0 and calculate UEPS2, BU0, ALPH3, ALPH4 again.

          UEPS2=(U0*EPS)**2
          arg = ueps2-factor**2
          if (arg < 0.) then
             arg = -1. * arg
          endif
          if (arg < resonc) then        
             IF(UEPS2.LT.FACTOR**2) THEN
                U0=U0-DELU0
             ELSE
                U0=U0+DELU0
             ENDIF
             UEPS2=(U0*EPS)**2
             BU0=0.5-U0/4.*(P1-3.*F)/(1.-F)  *SMOOTH2    
             ALPH3=W0*BU0*(1-F)
             ALPH4=W0*(1.-BU0)*(1-F)
          ENDIF

          GAM1=( FACTOR*ALPH3-U0*(ALPH1*ALPH3+ALPH2*ALPH4) ) * &
               &           1/(FACTOR**2-UEPS2)
          GAM2=(-FACTOR*ALPH4-U0*(ALPH1*ALPH4+ALPH2*ALPH3) ) * &
               &           1/(FACTOR**2-UEPS2)

          E=EXP(-EPS*TAUTOT)
          RM=ALPH2/(ALPH1+EPS)

          AL_CLR_4= E*(1-RM**2)/(1-E**2 * RM**2)
          AL_CLR_5= RM*(1-E**2)/(1-E**2 * RM**2)
          AL_CLR_1= EXP(-FACTOR*TAUTOT/U0)

          AL_CLR_2=-AL_CLR_4*GAM2-AL_CLR_5*GAM1*     &
               &                AL_CLR_1+GAM2*AL_CLR_1  
          AL_CLR_3=-AL_CLR_5*GAM2-AL_CLR_4*GAM1*     &
               &                AL_CLR_1+GAM1    

          !******************* second: cloudy sky *****************************
          ! For ECMWF input there is the possibility that cloud fraction occurs without a 
          ! corresponding value for lwc

          IF(  FRAC(K) > 0.02 .and. TS_PI_CLD(K,L) > 1.e-5 ) THEN


             TAUSCAT = TS_PI_CLR(K,L) + TAUS_CLD_col(K)
             TAUTOT  = TA_PI_CLR(K,L) + TAUA_CLD_col(K)+TAUSCAT
             G       = G_PI_CLD(K)*TAUS_CLD_col(K)/TAUSCAT 

             IF (TAUTOT > 0.) THEN
                W0=TAUSCAT/TAUTOT    
             ELSE
                W0=0.
             ENDIF

             W0 = MIN(W0,1.-1e-15)

             P1=3.*G
             F=G**2                        

             IF (P1<0.1) THEN
                SMOOTH1=1.33333333-P1*3.3333333
                SMOOTH2=10.*P1
             ELSE
                SMOOTH1=1
                SMOOTH2=1
             ENDIF

             B0=(3.-P1)/8.  *SMOOTH1                                 
             BU0=0.5-U0/4.*(P1-3.*F)/(1.-F)  *SMOOTH2    

             ALPH1=U*(1.-(1.-B0)*W0)     
             ALPH2=U*B0*W0               
             ALPH3=W0*BU0*(1-F)
             ALPH4=W0*(1.-BU0)*(1-F)

             EPS=SQRT(ALPH1**2-ALPH2**2)  



             FACTOR=1.-W0*F

             UEPS2=(U0*EPS)**2
             arg = ueps2-factor**2
             if (arg < 0.) then
                arg = -1. * arg
             endif

             if (arg < resonc) then 
                IF(UEPS2.LT.FACTOR**2) THEN
                   U0=U0-DELU0
                ELSE
                   U0=U0+DELU0
                ENDIF
                UEPS2=(U0*EPS)**2
                BU0=0.5-U0/4.*(P1-3.*F)/(1.-F)  *SMOOTH2    
                ALPH3=W0*BU0*(1-F)
                ALPH4=W0*(1.-BU0)*(1-F)
             ENDIF

             GAM1=( FACTOR*ALPH3-U0*(ALPH1*ALPH3+ALPH2*ALPH4) ) * 1/(FACTOR**2-UEPS2)
             GAM2=(-FACTOR*ALPH4-U0*(ALPH1*ALPH4+ALPH2*ALPH3) ) * 1/(FACTOR**2-UEPS2)

             E=EXP(-EPS*TAUTOT)
             RM=ALPH2/(ALPH1+EPS)

             AL_CLD_4=E*(1-RM**2)/(1-E**2 * RM**2)
             AL_CLD_5=RM*(1-E**2)/(1-E**2 * RM**2)
             AL_CLD_1=EXP(-FACTOR*TAUTOT/U0) 

             AL_CLD_2=-AL_CLD_4*GAM2-AL_CLD_5*GAM1*AL_CLD_1+GAM2*AL_CLD_1  
             AL_CLD_3=-AL_CLD_5*GAM2-AL_CLD_4*GAM1*AL_CLD_1+GAM1   

             AL(K,1) =(1-FRAC(K))*AL_CLR_1 + FRAC(K)*AL_CLD_1
             AL(K,2) =(1-FRAC(K))*AL_CLR_2 + FRAC(K)*AL_CLD_2
             AL(K,3) =(1-FRAC(K))*AL_CLR_3 + FRAC(K)*AL_CLD_3
             AL(K,4) =(1-FRAC(K))*AL_CLR_4 + FRAC(K)*AL_CLD_4
             AL(K,5) =(1-FRAC(K))*AL_CLR_5 + FRAC(K)*AL_CLD_5
          ELSE

             AL(K,1) =  AL_CLR_1
             AL(K,2) =  AL_CLR_2
             AL(K,3) =  AL_CLR_3
             AL(K,4) =  AL_CLR_4
             AL(K,5) =  AL_CLR_5

          ENDIF
       enddo !k

       !====================================================================
       ! matrix inversion
       !====================================================================

       !        direct solution of the first four equations       

       RF(1) = U0*FLUX(NL)
       RF(2) = 0.                              

       !       5th to 10th equation: bring matrix elements on the left of the main
       !       diagonal to the rhs:  save elements on the right of the main 
       !                             diagonal in array -tu(l,1)    

       RF(3) = AL(1,3) * RF(1)         
       RF(4) = AL(1,1) * RF(1)         
       RF(5) = AL(1,2) * RF(1)         

       TU1(1) = AL(1,4)        
       TU2(1) = AL(1,5)        

       !       blocks of 6 equations: eliminate left matrix elements, save right 
       !                              matrix elements in array -tu(l,i), 
       !                              calculate rhs.

       DO  K=2,lm(region)      
          K3=3*K              
          TD1       = 1./(1.-AL(K,5)*TU2(K-1))                  
          TD2       = AL(K,4)*TU2(K-1)        
          TU1(K)  = TD1*AL(K,4)
          TU2(K)  = AL(K,5) + TD2*TU1(K) 
          RF(K3)  = TD1 * (AL(K,3)*RF(K3-2) + AL(K,5)*RF(K3-1))     
          RF(K3+1)= AL(K,1)*RF(K3-2)      
          RF(K3+2)= AL(K,2)*RF(K3-2) + AL(K,4)*RF(K3-1)+TD2*RF(K3)
       enddo

       !        last two equations: the same as before 

       TDS1          = 1. / (1.-ALB*TU2(lm(region)))  
       rf(maxlev3) = tds1 * (alb * rf(maxlev3-2)+   &
            alb * rf(maxlev3-1))

       !        now we have created an upper triangular matrix the elements of which
       !        are -tu(l,i), 0, or 1 (in the main diagonal). the 0 and 1 elements 
       !        are not stored in an array. let us solve the system now and store the
       !        results in the arrays rf (fluxes clear sky) and rw (fluxes cloudy sky)

       DO  K=lm(region),1,-1         
          K3=3*K                  
          RF(K3+2) = RF(K3+2) + TU2(K)*RF(K3+3) 
          RF(K3)   = RF(K3) + TU1(K)*RF(K3+3)   
          SD(K+1,L)  = RF(K3+1)
          FD(K+1,L)  = RF(K3+2) 
          FU(K+1,L)  = RF(K3+3)
       enddo ! K  

       SD(1,L)  = RF(1) 
       FD(1,L)  = RF(2) 
       FU(1,L)  = RF(3)

       !        calculate the actinic flux                                     

       fact_top = sd(1,l)/u0 + u * fd(1,l)   + u * fu(1,l)

       do k = 1,lm(region)
          fact_bot = sd(k+1,l)/u0 + u * fd(k+1,l) + u * fu(k+1,l)
          fact(k,l) = max(0. ,(fact_top + fact_bot)/2.)
          fact_top = fact_bot   
       end do ! K

       ! swap vertical levels to the default order of the model
       fact(1:lm(region),l) = fact(lm(region):1:-1,l)
       cst_o3_col(1:lm(region),nl) = cst_o3_col(lm(region):1:-1,nl)

    enddo ! wavelength


    return                                                  

  END SUBROUTINE PIFM_RAN
  !EOC

  !------------------------------------------------------------------------------
  !                    TM5                                                      !
  !------------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:   SUNDIS
  !
  ! !DESCRIPTION: 
  !-----------------------------------------------------------------------------*
  !=  purpose:                                                                 =*
  !=  calculate earth-sun distance variation for a given date.  based on       =*
  !=  fourier coefficients originally from:  spencer, j.w., 1971, fourier      =*
  !=  series representation of the position of the sun, search, 2:172          =*
  !-----------------------------------------------------------------------------*
  !=  parameters:                                                              =*
  !=  idate  - integer, specification of the date, from yymmdd              (i)=*
  !=  esrm2  - real, variation of the earth-sun distance                    (o)=*
  !=           esrm2 = (average e/s dist)^2 / (e/s dist on day idate)^2        =*
  !-----------------------------------------------------------------------------*
  !=  edit history:                                                            =*
  !=  01/95  changed computation of trig function values                       =*
  !-----------------------------------------------------------------------------*
  != this program is free software;  you can redistribute it and/or modify     =*
  != it under the terms of the gnu general public license as published by the  =*
  != free software foundation;  either version 2 of the license, or (at your   =*
  != option) any later version.                                                =*
  != the tuv package is distributed in the hope that it will be useful, but    =*
  != without any warranty;  without even the implied warranty of merchantibi-  =*
  != lity or fitness for a particular purpose.  see the gnu general public     =*
  != license for more details.                                                 =*
  != to obtain a copy of the gnu general public license, write to:             =*
  != free software foundation, inc., 675 mass ave, cambridge, ma 02139, usa.   =*
  !-----------------------------------------------------------------------------*
  != to contact the authors, please mail to:                                   =*
  != sasha madronich, ncar/acd, p.o.box 3000, boulder, co, 80307-3000, usa  or =*
  != send email to:  sasha@ucar.edu                                            =*
  !-----------------------------------------------------------------------------*
  != copyright (c) 1994,95,96  university corporation for atmospheric research =*
  !-----------------------------------------------------------------------------*
  !\\
  !\\
  ! !INTERFACE:
  !
  REAL FUNCTION SUNDIS( imonth, iday)
    !
    ! !USES:
    !
    use binas, only : pi
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in) :: iday, imonth
    !
    ! !REVISION HISTORY: 
    !
    !EOP
    !------------------------------------------------------------------------------
    !BOC

    ! internal:
    integer mday, month, jday
    real dayn, thet0
    real sinth, costh, sin2th, cos2th

    integer,dimension(12) ::imn=(/ 31,28,31,30,31,30,31,31,30,31,30,31 /) 

    ! start

    ! parse date to find day number (julian day)

    mday = 0
    do  month = 1, imonth-1
       mday = mday + imn(month)               
    end do
    jday = mday + iday
    dayn = float(jday - 1) + 0.5

    ! define angular day number and compute esrm2:

    thet0 = 2.*pi*dayn/365.

    ! calculate sin(2*thet0), cos(2*thet0) from
    ! addition theoremes for trig functions for better
    ! performance;  the computation of sin2th, cos2th
    ! is about 5-6 times faster than the evaluation
    ! of the intrinsic functions sin and cos
    !
    sinth = sin(thet0)
    costh = cos(thet0)
    sin2th = 2.*sinth*costh
    cos2th = costh*costh - sinth*sinth
    sundis  = 1.000110 +   0.034221*costh  +  0.001280*sinth + &
         0.000719*cos2th +  0.000077*sin2th
    !

  END FUNCTION SUNDIS
  !EOC

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:   OZONE_INFO_ONLINE
  !
  ! !DESCRIPTION: calculate, from an ozone field, the overhead ozone at all
  !               grid points. 
  !               Optical depth clear sky conditions
  !               upper values are given by the ozone climatology above the
  !               highest model mid-level
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE OZONE_INFO_ONLINE( region )
    !
    ! !USES:
    !
    use binas,           only : Avog, xm_air, grav
    use dims
!    use photolysis_data, only : phot_dat
    use global_data,     only : region_dat, mass_dat
    use chem_param,      only : xmo3, io3
    use meteodata,       only : phlb_dat
    !
    ! !INPUT PARAMETERS:
    !
    integer, intent(in)  :: region
    !
    ! !REVISION HISTORY: 
    !      Jan 2003 - MK  - adapted for new TM5 memory structure.
    !      Jul 2008 - JEW - new ozone info unit coupled for online calculations
    !   26 Apr 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    real, parameter  :: conv = 0.1*Avog/xmo3   !  from kg/m2 --> #/cm2
    real, parameter  :: sp = Avog*1.e-4*0.2095/(xm_air*grav)

    integer :: i, j, l, lmr, i1, i2, j1, j2
    real,dimension(:,:,:),allocatable :: o3_overhead_online, o2_overhead   ! #/cm2
    real,dimension(:),    pointer     :: ozone_klimtop !in #cm-2
    real,dimension(:,:),  pointer     :: v3_surf       ! #/cm2
    real,dimension(:,:,:),pointer     :: v2, v3        ! #/cm2 
    real,dimension(:,:,:,:),pointer   :: o3            ! #/cm2 
    real,dimension(:,:,:),pointer     :: phlb
    real,dimension(:),    pointer     :: area

    
    call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
    lmr = lm(region)
    
    ! allocate on all prcessors so result maybe scattered   
    allocate(o3_overhead_online(i1:i2, j1:j2, lm(region))) ; o3_overhead_online = 0.0
    allocate(o2_overhead       (i1:i2, j1:j2, lm(region))) ; o2_overhead = 0.0

    v2 => phot_dat(region)%v2
    v3 => phot_dat(region)%v3
    v3_surf => phot_dat(region)%v3_surf

    area => region_dat(region)%dxyp
    phlb =>   phlb_dat(region)%data
    o3   =>   mass_dat(region)%rm    ! (i1:i2, j1:j2, 1:lmr, io3)

    ! CALCULATE COLUMNS
    ! -----------------

    ! (1) top
    ! --------
    ! o3du is not used anymore, except in cases where stratosphere is not resolved (EC-EARTH)

    if (with_o3du) then  ! use fortuin-kelder
       ozone_klimtop => phot_dat(region)%o3klim_top

       do j=j1,j2
       do i=i1,i2
             o3_overhead_online(i,j,lm(region)) = ozone_klimtop(j)  
       end do
       end do
       
    else ! from TM4-routine
       
       do j=j1,j2
       do i=i1,i2
             o3_overhead_online(i,j,lm(region)) =  0.5*conv*o3(i,j,lm(region),io3)/area(j)
       end do
       end do
       
    endif
    
    ! (2) rest
    ! --------
    do l = lm(region)-1,1,-1
       do j = j1,j2
       do i = i1,i2
             o3_overhead_online(i,j,l) = o3_overhead_online(i,j,l+1) + &
                  0.5*conv*(o3(i,j,l,io3)+o3(i,j,l+1,io3))/area(j)         
       enddo
       enddo
    enddo

    ! Define surface ozone column field for diagnostic purposes
    do j=j1,j2
    do i=i1,i2
          v3_surf(i,j) = o3_overhead_online(i,j,1) + 0.5*conv*o3(i,j,1,io3)/area(j)
    end do
    end do

    ! Boundaries
    v3(:,:,1) = o3_overhead_online(:,:,1)  

    ! now transform o3 column from layers to levels
    do l = 2,lm(region)
       v3(:,:,l) = ( o3_overhead_online(:,:,l) + o3_overhead_online(:,:,l-1) ) * 0.5 
    enddo

    ! TOA
    do j=j1,j2
    do i=i1,i2
          v3(i,j,lm(region)+1) = 0.5*v3(i,j,lm(region))
    enddo
    enddo

    ! determine oxygen columns (can directly be calculated on levels)
    do l = 1,lm(region)
    do j = j1,j2
    do i = i1,i2
             v2(i,j,l) = phlb(i,j,l)*sp
    enddo
    enddo
    enddo

    ! top boundary for v2 
    v2(:,:,lm(region)+1) = 0.5*v2(:,:,lm(region))

    nullify(o3)
    nullify(ozone_klimtop)
    nullify(area)
    nullify(phlb)

    nullify(v2)
    nullify(v3)
    nullify(v3_surf)

    deallocate(o3_overhead_online) 
    deallocate(o2_overhead) 

  END SUBROUTINE OZONE_INFO_ONLINE
  !EOC

  !--------------------------------------------------------------------------
  !                    TM5                                                  !
  !--------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    PHOTORATES_TROPO
  !
  ! !DESCRIPTION: calculation of photolysis and heating rates
  ! 
  !     References:                                                        
  !       J. Landgraf and P.J. Crutzen, 1998:                               
  !       An Efficient Methode for Online Calculation of Photolysis and     
  !       Heating Rates, J. Atmos. Sci., 55, 863-878
  ! 
  !     Expanded for high angles and online:
  !       J.E.Williams, J. Landgraf, B. Bregman and H. H. Walter, A modified band
  !       approach for the accurate calculation of online photolysis rates in
  !       stratospheric-tropospheric Chemistry Transport Models, Atms. Chem. Phys., 
  !       6, 4137-4161, 2006.
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE PHOTORATES_TROPO(region, zangle, cst_o3_col,   cst_no2_col, cst_hno3_col, cst_h2o2_col, &
                              cst_ch2o_col,   cst_n2o5_col, cst_pan_col, cst_no3_col, qy_no2_col, qy_o1d_col, &
                              qy_ch3cocho_col, qy_co_col,   qy_c2o3_col,  fact, fdir, rj, t_lay, debug_flag)
    !
    ! !USES:
    !
    use Dims,                only : im, jm, lm, idate
    use global_data,         only : mass_dat
    !
    ! !INPUT PARAMETERS:
    !
    integer,                                intent(in) :: region
    real,                                   intent(in) :: zangle
    real,dimension(lm(region),nbands_trop), intent(in) :: fact  !actinic flux
    real,dimension(lm(region),maxw),        intent(in) :: fdir  !flux o2-o3 abs.
    logical,                                intent(in) :: debug_flag
    real                                               :: tscale
    
    real,dimension(lm(region)),intent(in)              :: t_lay
    real,dimension(lm(region),maxwav),      intent(in) :: cst_o3_col
    real,dimension(lm(region),89),          intent(in) :: cst_no2_col,  qy_no2_col, qy_co_col, qy_c2o3_col
    real,dimension(lm(region),65),          intent(in) :: cst_hno3_col, qy_o1d_col
    real,dimension(lm(region),55),          intent(in) :: cst_n2o5_col
    real,dimension(lm(region),45),          intent(in) :: cst_h2o2_col
    real,dimension(lm(region),105),         intent(in) :: cst_ch2o_col
    real,dimension(lm(region),65),          intent(in) :: cst_pan_col
    real,dimension(lm(region),62),          intent(in) :: cst_no3_col
    real,dimension(lm(region),52),          intent(in) :: qy_ch3cocho_col   
    !
    ! !OUTPUT PARAMETERS:
    !
    real,dimension(lm(region),nj),         intent(out) :: rj  !photolysis rates 
    !
    ! !REVISION HISTORY: 
    !
    !EOP
    !------------------------------------------------------------------------
    !BOC

    real,dimension(nbands_trop)       :: bjo1d,     bjno2,    bjhno3, bjcoh2,  bjchoh,   bjn2o5a,  bjn2o5b,   &
                                         bjhno4,    bjpana,   bjpanb,    bjno2o,   bjnoo2, bjh2o2,  bjch3ooh, bjald2,   bjch3o2co, &
                                         bjch3cocho,bjch3ono2,bjo2  , bjispd,  bj_a_acet,bj_b_acet,bjhono

    !=================================================================================================
    !First tropospheric band is temperature independent for H2O2.N2O5,HCHO and NO2 therefore remove from large temp dep. arrays.
    real,dimension(17)      :: cs_h2o2, cs_n2o5,cs_ch2o,cs_no2, cs_o2

    data cs_h2o2 /4.34E-19,  4.07E-19,  3.85E-19,  3.63E-19,  3.41E-19,  3.18E-19,  2.95E-19, &  
         2.72E-19,  2.50E-19,  2.30E-19,  2.10E-19,  1.92E-19,  1.74E-19,  1.57E-19, &  
         1.41E-19,  1.26E-19,  1.13E-19/ 

    data cs_n2o5 /8.049E-18, 7.208E-18, 6.212E-18, 4.853E-18, 3.925E-18, 3.248E-18, 2.619E-18, &
         2.087E-18, 1.661E-18, 1.349E-18, 1.131E-18, 9.549E-19, 8.353E-18, 7.427E-19, &
         6.762E-19, 6.095E-19, 5.229E-19/ 

    data  cs_ch2o /0.00E+00, 0.00E+00, 0.00E+00, 0.00E+00, 0.00E+00, 0.00E+00, 0.00E+00, &
         0.00E+00, 0.00E+00, 0.00E+00, 0.00E+00, 1.844E-22, 3.311E-22, 3.198E-22, &
         6.982E-22, 7.341E-22, 1.383E-21/

    data cs_o2 /7.448E-24, 7.322E-24, 7.002E-24, 6.608E-24, 6.118E-24, 5.736E-24, 5.302E-24,&
         4.741E-24, 4.261E-24, 3.788E-24, 3.213E-24, 2.69E-24, 2.218E-24, 1.793E-24,&
         1.384E-24, 1.054E-24, 6.318E-25/              

    real,dimension(62)      :: cs_hno4 ! 
    ! Reference : JPL 2006, 4-40 
    data cs_hno4 /4.43E-18,  3.64E-18,  3.09E-18,  2.54E-18,  2.13E-18,  1.78E-18,  1.51E-18, &  
         1.30E-18,  1.13E-18,  1.01E-18,  9.07E-19,  8.33E-19,  7.65E-19,  7.06E-19, &  
         6.48E-19,  5.91E-19,  5.36E-19,  4.83E-19,  4.36E-19,  3.93E-19,  3.53E-19, &   
         3.10E-19,  2.69E-19,  2.31E-19,  1.96E-19,  1.61E-19,  1.27E-19,  9.53E-20, &  
         7.01E-20,  4.93E-20,  3.31E-20,  2.14E-20,  1.60E-20,  1.40E-20,  1.30E-20, &  
         1.20E-20,  1.10E-20,  1.00E-20,  9.00E-21,  8.20E-21,  7.40E-21,  6.60E-21, &  
         5.80E-21,  5.00E-21,  4.60E-21,  4.20E-21,  3.80E-21,  3.40E-21,  3.00E-21, &  
         2.80E-21,  2.60E-21,  2.40E-21,  2.20E-21,  2.00E-21,  1.80E-21,  1.50E-21, &  
         1.10E-21,  7.00E-22,  0.00E+00,  0.00E+00,  0.00E+00,  0.00E+00/
         
    ! Reference : IUPAC, P21
    real,dimension(65)       :: qy_pan  
    data qy_pan /  7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, &
        7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, &
        7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, 7.589E-01, 7.511E-01, 7.431E-01, &
        7.348E-01, 7.264E-01, 7.177E-01, 7.089E-01, 6.997E-01, 6.903E-01, 6.807E-01, &
        6.708E-01, 6.606E-01, 6.501E-01, 6.393E-01, 6.325E-01, 6.300E-01, 6.275E-01, &
        6.250E-01, 6.225E-01, 6.200E-01, 6.175E-01, 6.150E-01, 6.125E-01, 6.100E-01, &
        5.995E-01, 5.890E-01, 5.785E-01, 5.680E-01, 5.575E-01, 5.470E-01, 5.365E-01, &
        5.260E-01, 5.155E-01, 5.050E-01, 4.945E-01, 4.840E-01, 4.735E-01, 4.577E-01, & 
        4.367E-01, 4.157E-01, 3.800E-01, 3.300E-01, 2.800E-01, 2.300E-01, 0.000E+00, &
        0.000E+00, 0.000E+00/     
    real, dimension(89)     :: cs_hono
    ! Reference : IUPAC 2001, datasheet PNOx1
    data cs_hono /2.110E-18, 2.198E-18, 2.173E-18, 2.147E-18, 2.025E-18, 1.867E-18, 1.710E-18, &
       1.554E-18, 1.408E-18, 1.280E-18, 1.133E-18, 9.571E-19, 8.147E-19, 7.137E-19, &
       6.104E-19, 5.046E-19, 3.962E-19, 2.908E-19, 2.207E-19, 1.685E-19, 1.348E-19, &
       1.003E-19, 7.195E-20, 5.256E-20, 3.956E-20, 3.020E-20, 2.069E-20, 1.399E-21, &
       0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 1.400E-21, &
       2.800E-21, 4.200E-21, 5.600E-21, 7.000E-21, 8.800E-21, 1.060E-20, 1.240E-20, &
       1.420E-20, 1.600E-20, 1.780E-20, 1.960E-20, 2.140E-20, 2.320E-20, 2.500E-20, &
       2.880E-20, 3.260E-20, 3.640E-20, 4.020E-20, 4.400E-20, 4.520E-20, 4.700E-20, &
       4.940E-20, 6.290E-20, 9.300E-20, 1.305E-19, 1.680E-19, 9.600E-20, 1.150E-19, &
       2.360E-19, 8.000E-20, 1.610E-19, 2.050E-19, 4.900E-20, 9.200E-20, 1.450E-19, &
       2.400E-20, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, &
       0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, &
       0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00/

    real, dimension(89)     :: cs_ch3ooh
    ! Reference : JPL 2011, D9  
    data cs_ch3ooh / 2.782E-19, 2.782E-19, 2.782E-19, 2.782E-19, 2.782E-19, 2.316E-19, 1.956E-19, & 
         1.696E-19, 1.476E-19, 1.318E-19, 1.169E-19, 1.036E-19, 9.132E-20, 8.045E-20, &
         7.084E-20, 6.199E-20, 5.483E-20, 4.808E-20, 4.260E-20, 3.744E-20, 3.263E-20, & 
         2.819E-20, 2.431E-20, 2.119E-20, 1.827E-20, 1.569E-20, 1.338E-20, 1.107E-20, & 
         9.226E-21, 7.677E-21, 6.358E-21, 5.152E-21, 4.406E-21, 4.130E-21, 3.930E-21, & 
         3.730E-21, 3.530E-21, 3.330E-21, 3.130E-21, 2.982E-21, 2.834E-21, 2.686E-21, &  
         2.538E-21, 2.390E-21, 2.276E-21, 2.162E-21, 2.048E-21, 1.934E-21, 1.820E-21, & 
         1.730E-21, 1.640E-21, 1.550E-21, 1.460E-21, 1.370E-21, 1.306E-21, 1.210E-21, & 
         1.082E-21, 9.720E-22, 7.900E-22, 6.100E-22, 4.700E-22, 3.500E-22, 2.700E-22, & 
         2.100E-22, 1.600E-22, 1.200E-22, 7.500E-23, 5.200E-23, 4.000E-23, 4.050E-23, &
         4.100E-23, 1.000E-23, 6.000E-24, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, &
         0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, &
         0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00/

    real, dimension(120)     :: cs_ch3cocho
    ! Reference : JPL 2006, P 4-71  
    data cs_ch3cocho /2.280E-19, 1.489E-19, 9.624E-20, 6.968E-20, 5.036E-20, 3.627E-20, 2.581E-20, & 
         1.729E-20, 1.440E-20, 1.435E-20, 1.460E-20, 1.521E-20, 1.619E-20, 1.743E-20, & 
         1.908E-20, 2.036E-20, 2.207E-20, 2.312E-20, 2.509E-20, 2.697E-20, 2.807E-20, & 
         3.175E-20, 3.343E-20, 3.580E-20, 4.070E-20, 4.234E-20, 4.473E-20, 4.906E-20, & 
         4.782E-20, 4.712E-20, 4.813E-20, 4.120E-20, 3.760E-20, 3.690E-20, 3.700E-20, & 
         3.740E-20, 3.740E-20, 3.620E-20, 3.380E-20, 3.150E-20, 2.920E-20, 2.710E-20, & 
         2.520E-20, 2.340E-20, 2.180E-20, 2.060E-20, 1.970E-20, 1.900E-20, 1.860E-20, & 
         1.860E-20, 1.870E-20, 1.820E-20, 1.680E-20, 1.500E-20, 1.340E-20, 1.180E-20, & 
         9.670E-21, 8.110E-21, 6.470E-21, 4.950E-21, 3.220E-21, 2.950E-21, 3.850E-21, & 
         5.560E-21, 7.650E-21, 1.080E-20, 1.470E-20, 1.900E-20, 2.420E-20, 3.200E-20, & 
         4.030E-20, 4.670E-20, 5.620E-20, 6.920E-20, 8.520E-20, 9.690E-20, 1.020E-19, & 
         1.030E-19, 1.040E-19, 1.080E-19, 9.940E-20, 9.620E-20, 8.680E-20, 3.690E-20, & 
         9.140E-21, 2.680E-21, 1.080E-21, 6.270E-22, 3.920E-22, 2.430E-22, 1.740E-22, & 
         0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, &
         0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, &
         0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, &
         0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, &
         0.000E+00/

    real,dimension(62)      :: cs_orgn
    ! Reference : average 1-C4H9ONO2 & 2-C4H9ONO2 (IUPAC data sheet P18 and P19)
    ! JEW: The absorption spectrum of 2-C4H9ONO2 is mirrored around the maxiumum.
    data cs_orgn / 5.250E-018, 4.398E-018, 3.609E-018, 2.804E-018, 2.172E-018, 1.595E-018, 1.130E-018, &
         7.710E-019, 5.025E-019, 3.714E-019, 2.623E-019, 1.900E-019, 1.342E-019, 9.905E-020, &
         7.285E-020, 5.245E-020, 4.052E-020, 3.110E-020, 2.806E-020, 5.649E-020, 5.136E-020, &
         4.886E-020, 4.635E-020, 4.358E-020, 3.970E-020, 3.610E-020, 3.247E-020, 2.784E-020, &
         2.308E-020, 1.846E-020, 1.401E-020, 9.810E-021, 7.430E-021, 6.550E-021, 6.080E-021, &
         5.610E-021, 5.140E-021, 4.670E-021, 4.200E-021, 3.840E-021, 3.480E-021, 3.120E-021, &
         2.760E-021, 2.400E-021, 2.170E-021, 1.940E-021, 1.710E-021, 1.480E-021, 1.250E-021, &
         1.131E-021, 1.012E-021, 8.930E-022, 7.740E-022, 2.550E-022, 2.350E-022, 2.050E-022, &
         1.650E-022, 1.400E-022, 1.050E-022, 8.000E-023, 0.000E+000, 0.000E+000/

    real, dimension(89)     :: cs_ald2         
    ! Reference : average CH3CHO & C2H5CHO (JPL and IUPAC data sheet, respectively)
    data cs_ald2 /5.211E-022, 5.133E-022, 5.163E-022, 5.272E-022, 5.526E-022, 5.837E-022, 6.266E-022, &
         6.774E-022, 7.498E-022, 8.806E-022, 1.054E-021, 1.387E-021, 1.849E-021, 2.472E-021, &
         3.444E-021, 4.679E-021, 6.217E-021, 8.229E-021, 1.074E-020, 1.376E-020, 1.729E-020, &
         2.131E-020, 2.584E-020, 3.082E-020, 3.565E-020, 4.055E-020, 4.482E-020, 4.809E-020, &
         5.184E-020, 5.155E-020, 5.245E-020, 4.795E-020, 4.640E-020, 4.600E-020, 4.540E-020, &
         4.465E-020, 4.330E-020, 4.085E-020, 3.870E-020, 3.730E-020, 3.585E-020, 3.490E-020, &
         3.380E-020, 3.265E-020, 3.145E-020, 3.015E-020, 2.895E-020, 2.750E-020, 2.485E-020, &
         2.235E-020, 2.125E-020, 1.990E-020, 1.869E-020, 1.777E-020, 1.631E-020, 1.471E-020, &
         1.254E-020, 1.014E-020, 6.315E-021, 3.375E-021, 1.525E-021, 2.300E-022, 9.000E-023, &
         3.000E-023, 1.500E-023, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
         0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
         0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
         0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000/
                 
    real, dimension(89)     :: cs_ispd
    ! Reference : average MACR and MVK (IUPAC data sheets)      1st two bins are estimates
    data cs_ispd /0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
                  0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
                  0.000E+000, 0.000E+000, 0.000E+000, 1.700E-021, 1.900E-021, 2.107E-021, 2.157E-021, &
                  2.403E-021, 2.928E-021, 3.713E-021, 4.854E-021, 6.439E-021, 8.562E-021, 1.147E-020, &
                  1.496E-020, 1.942E-020, 2.471E-020, 3.088E-020, 3.480E-020, 3.655E-020, 3.825E-020, &
                  3.980E-020, 4.130E-020, 4.275E-020, 4.425E-020, 4.610E-020, 4.770E-020, 4.920E-020, &
                  5.055E-020, 5.180E-020, 5.355E-020, 5.540E-020, 5.685E-020, 5.815E-020, 5.920E-020, &
                  6.075E-020, 6.230E-020, 6.365E-020, 6.455E-020, 6.485E-020, 6.470E-020, 6.558E-020, &
                  6.788E-020, 6.880E-020, 7.215E-020, 6.510E-020, 6.340E-020, 6.380E-020, 4.680E-020, &
                  4.145E-020, 4.365E-020, 2.680E-020, 1.650E-020, 1.144E-020, 1.175E-020, 5.440E-021, &
                  2.455E-021, 1.525E-021, 2.300E-022, 9.000E-023, 0.000E+000, 0.000E+000, 0.000E+000, &
                  0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
                  0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000/
    ! Reference : 5 abs. spectra at 5 different temperatures for acetone (235,254,263,280,298)
    real, dimension(77)     :: cs_ch3coch3_235
    data cs_ch3coch3_235 /1.185E-018, 9.785E-019, 7.682E-019, 5.534E-019, 3.341E-019, 1.102E-019, 1.875E-21, &
                          2.253E-021, 2.749E-021, 3.370E-021, 4.256E-021, 5.246E-021, 6.592E-021, 8.226E-21, &
                          1.025E-020, 1.277E-020, 1.562E-020, 1.898E-020, 2.278E-020, 2.694E-020, 3.129E-20, &
                          3.568E-020, 3.973E-020, 4.352E-020, 4.592E-020, 4.791E-020, 4.753E-020, 4.708E-20, &
                          4.391E-020, 4.018E-020, 3.524E-020, 2.906E-020, 2.510E-020, 2.370E-020, 2.280E-20, &
                          2.160E-020, 2.020E-020, 1.910E-020, 1.790E-020, 1.640E-020, 1.500E-020, 1.360E-20, &
                          1.250E-020, 1.130E-020, 1.020E-020, 9.320E-021, 8.620E-021, 7.630E-021, 6.710E-21, &
                          6.030E-021, 5.370E-021, 4.610E-021, 3.940E-021, 3.330E-021, 2.890E-021, 2.130E-21, &
                          1.390E-021, 8.720E-022, 3.550E-022, 1.200E-022, 5.110E-023, 1.590E-023, 0.000E+00, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+00, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+00/     
    real, dimension(77)     :: cs_ch3coch3_254
    data cs_ch3coch3_254 /1.177E-018, 9.719E-019, 7.630E-019, 5.497E-019, 3.319E-019, 1.095E-019, 1.892E-021, &
                          2.257E-021, 2.729E-021, 3.321E-021, 4.176E-021, 5.134E-021, 6.450E-021, 8.067E-021, &
                          1.005E-020, 1.252E-020, 1.532E-020, 1.868E-020, 2.248E-020, 2.660E-020, 3.089E-020, &
                          3.537E-020, 3.937E-020, 4.321E-020, 4.567E-020, 4.772E-020, 4.761E-020, 4.723E-020, &
                          4.428E-020, 4.068E-020, 3.584E-020, 2.986E-020, 2.590E-020, 2.450E-020, 2.360E-020, &
                          2.240E-020, 2.100E-020, 1.990E-020, 1.860E-020, 1.710E-020, 1.570E-020, 1.440E-020, &
                          1.320E-020, 1.200E-020, 1.090E-020, 9.940E-021, 9.190E-021, 8.150E-021, 7.190E-021, &
                          6.480E-021, 5.790E-021, 4.990E-021, 4.300E-021, 3.670E-021, 3.240E-021, 2.430E-021, &
                          1.630E-021, 1.056E-021, 4.500E-022, 1.450E-022, 5.400E-023, 1.810E-023, 0.000E+000, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000/    
    real, dimension(77)     :: cs_ch3coch3_263
    data cs_ch3coch3_263 /1.177E-018, 9.719E-019, 7.630E-019, 5.497E-019, 3.319E-019, 1.095E-019, 1.892E-021, & 
                          2.257E-021, 2.729E-021, 3.321E-021, 4.176E-021, 5.134E-021, 6.450E-021, 8.067E-021, & 
                          1.005E-020, 1.252E-020, 1.532E-020, 1.868E-020, 2.248E-020, 2.660E-020, 3.089E-020, & 
                          3.537E-020, 3.937E-020, 4.321E-020, 4.567E-020, 4.772E-020, 4.761E-020, 4.723E-020, & 
                          4.428E-020, 4.068E-020, 3.584E-020, 2.986E-020, 2.590E-020, 2.450E-020, 2.360E-020, &
                          2.240E-020, 2.100E-020, 1.990E-020, 1.860E-020, 1.710E-020, 1.570E-020, 1.440E-020, &
                          1.320E-020, 1.200E-020, 1.090E-020, 9.940E-021, 9.190E-021, 8.150E-021, 7.190E-021, &
                          6.480E-021, 5.790E-021, 4.990E-021, 4.300E-021, 3.670E-021, 3.240E-021, 2.430E-021, &
                          1.630E-021, 1.056E-021, 4.500E-022, 1.450E-022, 5.400E-023, 1.810E-023, 0.000E+000, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000/
    real, dimension(77)     :: cs_ch3coch3_280                       
    data cs_ch3coch3_280 /1.196E-018, 9.883E-019, 7.759E-019, 5.590E-019, 3.375E-019, 1.112E-019, 1.855E-021, &
                          2.233E-021, 2.719E-021, 3.340E-021, 4.225E-021, 5.200E-021, 6.540E-021, 8.166E-021, &
                          1.015E-020, 1.262E-020, 1.542E-020, 1.878E-020, 2.258E-020, 2.674E-020, 3.109E-020, &
                          3.558E-020, 3.967E-020, 4.361E-020, 4.627E-020, 4.843E-020, 4.851E-020, 4.823E-020, &
                          4.541E-020, 4.188E-020, 3.714E-020, 3.106E-020, 2.710E-020, 2.570E-020, 2.480E-020, &
                          2.350E-020, 2.200E-020, 2.080E-020, 1.960E-020, 1.800E-020, 1.660E-020, 1.530E-020, &
                          1.410E-020, 1.280E-020, 1.170E-020, 1.070E-020, 9.930E-021, 8.820E-021, 7.790E-021, &
                          7.040E-021, 6.310E-021, 5.480E-021, 4.760E-021, 4.100E-021, 3.650E-021, 2.795E-021, &
                          1.940E-021, 1.305E-021, 5.880E-022, 1.930E-022, 7.200E-023, 2.380E-023, 0.000E+000, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000/
    real, dimension(77)     :: cs_ch3coch3_298                       
    data cs_ch3coch3_298 /1.246E-019, 1.032E-019, 8.135E-020, 5.903E-020, 3.623E-020, 1.295E-020, 1.835E-021, &
                          2.213E-021, 2.699E-021, 3.310E-021, 4.186E-021, 5.166E-021, 6.490E-021, 8.097E-021, &
                          1.007E-020, 1.257E-020, 1.542E-020, 1.878E-020, 2.258E-020, 2.680E-020, 3.125E-020, &
                          3.578E-020, 3.997E-020, 4.401E-020, 4.677E-020, 4.913E-020, 4.931E-020, 4.913E-020, &
                          4.648E-020, 4.298E-020, 3.824E-020, 3.216E-020, 2.820E-020, 2.670E-020, 2.580E-020, &
                          2.450E-020, 2.300E-020, 2.180E-020, 2.050E-020, 1.890E-020, 1.750E-020, 1.610E-020, &
                          1.490E-020, 1.360E-020, 1.240E-020, 1.140E-020, 1.060E-020, 9.440E-021, 8.370E-021, &
                          7.600E-021, 6.840E-021, 5.980E-021, 5.230E-021, 4.550E-021, 4.110E-021, 3.210E-021, &
                          2.290E-021, 1.575E-021, 7.400E-022, 2.480E-022, 9.120E-023, 3.010E-023, 0.000E+000, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, &
                          0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000, 0.000E+000/
                       
    real, dimension(77)     :: cs_ch3coch3                                       
    !==========================================================================================================
    ! Similar procedure for quantum yields for : HCHO and NO3. A quantum yield of 0.8 is adopted for JN2O5 below 305nm
    ! as recommended in JPL 2006 - JEW 2009        
    real,dimension(90)       :: qyh_hco,qyh2_co
    real,dimension(62)       :: qyno2_o,qyno_o2

    data qyh_hco  /0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,  & 
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,  &
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 3.087E-01, 3.087E-01, 3.030E-01,  &   
                   3.113E-01, 3.325E-01, 3.649E-01, 4.059E-01, 4.535E-01, 5.061E-01, 5.611E-01,  & 
                   6.159E-01, 6.662E-01, 7.097E-01, 7.418E-01, 7.550E-01, 7.580E-01, 7.610E-01,  & 
                   7.620E-01, 7.620E-01, 7.620E-01, 7.600E-01, 7.580E-01, 7.540E-01, 7.490E-01,  & 
                   7.440E-01, 7.370E-01, 7.290E-01, 7.200E-01, 7.090E-01, 6.980E-01, 6.850E-01,  & 
                   6.710E-01, 6.560E-01, 6.390E-01, 6.220E-01, 6.030E-01, 5.830E-01, 5.500E-01,  & 
                   5.020E-01, 4.490E-01, 3.430E-01, 1.650E-01, 0.000E+00, 0.000E+00, 0.000E+00,  &
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,  & 
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,  &
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,  &  
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00/ !(JPL 2006, p4-47) 
                           
    data qyh2_co  /0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,   &   
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,   &
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 4.913E-01, 4.913E-01, 4.970E-01,   & 
                   4.887E-01, 4.697E-01, 4.546E-01, 4.313E-01, 4.020E-01, 3.682E-01, 3.440E-01,   & 
                   3.152E-01, 2.922E-01, 2.662E-01, 2.547E-01, 2.450E-01, 2.420E-01, 2.390E-01,   & 
                   2.380E-01, 2.380E-01, 2.380E-01, 2.400E-01, 2.420E-01, 2.460E-01, 2.510E-01,   & 
                   2.560E-01, 2.630E-01, 2.710E-01, 2.800E-01, 2.910E-01, 3.020E-01, 3.150E-01,   & 
                   3.290E-01, 3.440E-01, 3.610E-01, 3.780E-01, 3.970E-01, 4.170E-01, 4.500E-01,   &  
                   4.980E-01, 5.510E-01, 6.570E-01, 7.350E-01, 6.500E-01, 5.000E-01, 3.800E-01,   & 
                   2.200E-01, 4.000E-03, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,   &  
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,   & 
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00,   &  
                   0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00, 0.000E+00/
                                
    data qyno2_o /0.9,  0.9,       0.9,      0.9,      0.9,     0.9,     0.9,               & 
                  0.9,  0.9,       0.9,      0.9,      0.9,     0.9,     0.9,               &
                  0.9,  0.9,       0.9,      0.9,      0.9,     0.9,     1.00,              &
                  1.00,  1.00,     1.00,     1.00,     1.00,    1.00,    1.00,              &
                  1.00,  1.00,     1.00,     1.00,     1.00,    1.00,    1.00,              & 
                  1.00,  1.00,     1.00,     1.00,     1.00,    1.00,    1.00,              &
                  1.00,  1.00,     1.00,     1.00,     1.00,    1.00,    1.00,              &
                  1.00,  0.83,     0.65,     0.58,     0.51,    0.43,    0.36,              &
                  0.29,  0.22,     0.14,     0.07,     0.0,     0.0/

    data qyno_o2 /0.0,  0.0,       0.0,      0.0,      0.0,     0.0,     0.0,               & 
                  0.0,  0.0,       0.0,      0.0,      0.0,     0.0,     0.0,               &
                  0.0,  0.0,       0.0,      0.0,      0.0,     0.0,     0.0,               &
                  0.0,  0.0,       0.0,      0.0,      0.0,     0.0,     0.0,               &
                  0.0,  0.0,       0.0,      0.0,      0.0,     0.0,     0.0,               & 
                  0.0,  0.0,       0.0,      0.0,      0.0,     0.0,     0.0,               &
                  0.0,  0.0,       0.0,      0.0,      0.0,     0.0,     0.0,               &
                  0.0,  0.18,      0.35,     0.31,     0.27,    0.23,    0.19,              &
                  0.16,  0.12,     0.08,     0.04,     0.0,     0.0/

    !========================================================================================================

    integer               :: i, j, l, k, c
    real                  :: delta1, delta2, delta3, delta4, delta5, delta6, delta7, delta1_spec, delta3_spec
    integer, dimension(7) :: band_start, band_middle, band_end
    logical               :: daylight

    ! ==============================================================        
    ! CALCULATION PHOTOLYSIS RATES FOR SCATTERING ATMOSPHERE             
    ! ============================================================== 

    ! the check for daylight is skipped as the calculation of rj is only called within the photo_flux loop
    ! where a filter already applies

    rj(:,:) = 0.
                       
    ! choose the grid settings dependent on the SZA for the column       
    if(zangle<=71.) then
       band_start(:)=lini(:)
       band_middle(:)=lmid(:)
       band_end(:)=lfin(:)
    elseif(zangle>71. .and. zangle<=sza_limit) then
       band_start(:)=lini_gridA(:)
       band_middle(:)=lmid_gridA(:)
       band_end(:)=lfin_gridA(:)
    endif

    do k = 1,lm(region)         
       ! re-initialize bj values               
       do l = 1,nbands_trop    
          bjo1d(l)      = 0.0     
          bjno2(l)      = 0.0     
          bjhno3(l)     = 0.0     
          bjcoh2(l)     = 0.0     
          bjchoh(l)     = 0.0
          bjn2o5a(l)    = 0.0
          bjn2o5b(l)    = 0.0     
          bjhno4(l)     = 0.0
          bjhono(l)     = 0.0    
          bjno2o(l)     = 0.0     
          bjnoo2(l)     = 0.0     
          bjh2o2(l)     = 0.0     
          bjch3ooh(l)   = 0.0  
          bjpana(l)     = 0.0
          bjpanb(l)     = 0.0     
          bjald2(l)     = 0.0
          bjch3cocho(l) = 0.0  
          bjch3ono2(l) = 0.0
          bjo2(l)      = 0.0
          bjispd(l)    = 0.0
          bj_a_acet(l) = 0.0
          bj_b_acet(l) = 0.0
       end do
       !                                      
       ! assign cs_ch3coch3  w/ a good value
       !
       ! linearly interpolate to try and improve on J values
       !
       if(t_lay(k)<=235.) cs_ch3coch3=cs_ch3coch3_235
       if(t_lay(k)>235. .and. t_lay(k)<=254.) then
          tscale=(t_lay(k)-235.)/19.0
          cs_ch3coch3=((1.0-tscale)*cs_ch3coch3_235)+(tscale*cs_ch3coch3_254)
       endif
       if(t_lay(k)>254. .and. t_lay(k)<=263.) then
          tscale=(t_lay(k)-254.)/9.0
          cs_ch3coch3=((1.0-tscale)*cs_ch3coch3_254)+(tscale*cs_ch3coch3_263)
       endif
       if(t_lay(k)>263. .and. t_lay(k)<=280.) then
          tscale=(t_lay(k)-264.)/16.0
          cs_ch3coch3=((1.0-tscale)*cs_ch3coch3_263)+(tscale*cs_ch3coch3_280)
       endif
       if(t_lay(k)>280.) then
          tscale=(t_lay(k)-280.)/18.0 
          cs_ch3coch3=((1.0-tscale)*cs_ch3coch3_280)+(tscale*cs_ch3coch3_298)
       endif
       !==============================================================================================
       ! re-initialize the temporary arrays for the next layer
       !=============================================================================================== 

       delta1 = 0. ; delta2 = 0. ;delta3 = 0. ; delta4 = 0. ; delta5 = 0. ; delta6 = 0. ; delta7 = 0.
       delta1_spec = 0. ; delta3_spec = 0.

       ! =====================================================================================
       !       Tropo band 1
       ! =====================================================================================
       ! temp indep species for this band: no2,h2o2,n2o5,hno4,ch2o,ch3ooh,ald2,orgntr
       do l = band_start(1),band_end(1) 
          bjo1d(1)  = bjo1d(1) + cst_o3_col(k,l)*qy_o1d_col(k,l)*fdir(k,l)
          bjno2(1)  = bjno2(1) + cst_no2_col(k,l)*qy_no2_col(k,l)*fdir(k,l)
          bjh2o2(1) = bjh2o2(1) + cs_h2o2(l)*fdir(k,l)
          bjhno3(1) = bjhno3(1) + cst_hno3_col(k,l)*fdir(k,l)
          bjhno4(1) = bjhno4(1) + cs_hno4(l)*fdir(k,l)
          bjhono(1) = bjhono(1) + cs_hono(l)*fdir(k,l)        
          bjn2o5a(1)= bjn2o5a(1) + 0.8*cs_n2o5(l)*fdir(k,l)
          bjn2o5b(1)= bjn2o5b(1) + 0.2*cs_n2o5(l)*fdir(k,l)
          bjchoh(1) = bjchoh(1) + cs_ch2o(l)*qyh_hco(l)*fdir(k,l)    
          bjch3ooh(1) = bjch3ooh(1) + cs_ch3ooh(l)*fdir(k,l)
          bjald2(1)   = bjald2(1) + cs_ald2(l)*fdir(k,l)
          bjpana(1)    = bjpana(1) + cst_pan_col(k,l)*qy_pan(l)*fdir(k,l)
          bjpanb(1)    = bjpanb(1) + cst_pan_col(k,l)*(1.0-qy_pan(l))*fdir(k,l)  
          bjch3ono2(1) = bjch3ono2(1) + cs_orgn(l) * fdir(k,l)
          bjo2(1) = bjo2(1) + cs_o2(l) * fdir(k,l)   
       end do

       ! ===================================================================================== 
       !           Tropo band 2                                                      
       ! =====================================================================================
       ! temp indep species for this band: hno4,ch3ooh,ald2,orgntr
       do l = band_start(2),band_end(2) ! temp indep for : no2,hno4,ch2o,ch3ooh,orgntr
          bjo1d(2)       = bjo1d(2) + cst_o3_col(k,l)*qy_o1d_col(k,l)*fdir(k,l)
          bjno2(2)       = bjno2(2) + cst_no2_col(k,l)*qy_no2_col(k,l)*fdir(k,l)
          bjh2o2(2)      = bjh2o2(2) + cst_h2o2_col(k,l-17)*fdir(k,l)
          bjhno3(2)      = bjhno3(2) + cst_hno3_col(k,l)*fdir(k,l)
          bjhno4(2)      = bjhno4(2) + cs_hno4(l)*fdir(k,l)
          bjhono(2)      = bjhono(2) + cs_hono(l)*fdir(k,l)
          bjn2o5a(2)     = bjn2o5a(2) + 0.8*cst_n2o5_col(k,l-17)*fdir(k,l)
          bjn2o5b(2)     = bjn2o5b(2) + 0.2*cst_n2o5_col(k,l-17)*fdir(k,l)
          bjcoh2(2)      = bjcoh2(2) + cst_ch2o_col(k,l-17)*qyh2_co(l)*fdir(k,l)    
          bjchoh(2)      = bjchoh(2) + cst_ch2o_col(k,l-17)*qyh_hco(l)*fdir(k,l)                             
          bjch3ooh(2)    = bjch3ooh(5) + cs_ch3ooh(l)*fdir(k,l)
          bjpana(2)      = bjpana(2) + cst_pan_col(k,l)*qy_pan(l)*fdir(k,l)
          bjpanb(2)      = bjpanb(2) + cst_pan_col(k,l)*(1.0-qy_pan(l))*fdir(k,l)
          bjald2(2)      = bjald2(2) + cs_ald2(l)*fdir(k,l)
          bjch3cocho(2)  = bjch3cocho(2) + cs_ch3cocho(l)*fdir(k,l)
          bjch3ono2(2)   = bjch3ono2(2) + cs_orgn(l) * fdir(k,l)
          bjispd(2)      = bjispd(2) + cs_ispd(l) * fdir(k,l)
          bj_a_acet(2)   = bj_a_acet(2) + cs_ch3coch3(l)*qy_co_col(k,l)*fdir(k,l)              
          bj_b_acet(2)   = bj_b_acet(2) + cs_ch3coch3(l)*qy_c2o3_col(k,l)*fdir(k,l)       
       end do

       ! ======================================================================================= 
       !           Tropo band 3                                                      
       ! ======================================================================================= 
       ! temp indep species for this band: hno4,ch3ooh,ald2,mgly,orgntr      
       do l = band_start(3),band_end(3)
          bjo1d(3)       = bjo1d(3) + cst_o3_col(k,l)*qy_o1d_col(k,l)*fdir(k,l)
          bjno2(3)       = bjno2(3) + cst_no2_col(k,l)*qy_no2_col(k,l)*fdir(k,l)
          bjh2o2(3)      = bjh2o2(3) + cst_h2o2_col(k,l-17)*fdir(k,l)
          bjhno3(3)      = bjhno3(3) + cst_hno3_col(k,l)*fdir(k,l)
          bjhno4(3)      = bjhno4(3) + cs_hno4(l)*fdir(k,l)
          bjhono(3)      = bjhono(3) + cs_hono(l)*fdir(k,l)
          bjn2o5a(3)     = bjn2o5a(3) + 0.9*cst_n2o5_col(k,l-17)*fdir(k,l)
          bjn2o5b(3)     = bjn2o5b(3) + 0.1*cst_n2o5_col(k,l-17)*fdir(k,l)
          bjcoh2(3)      = bjcoh2(3) + cst_ch2o_col(k,l-17)*qyh2_co(l)*fdir(k,l)                      
          bjchoh(3)      = bjchoh(3) + cst_ch2o_col(k,l-17)*qyh_hco(l)*fdir(k,l)                                 
          bjch3ooh(3)    = bjch3ooh(3) + cs_ch3ooh(l)*fdir(k,l)
          bjpana(3)      = bjpana(3) + cst_pan_col(k,l)*qy_pan(l)*fdir(k,l)
          bjpanb(3)      = bjpanb(3) + cst_pan_col(k,l)*(1.0-qy_pan(l))*fdir(k,l)
          bjald2(3)      = bjald2(3) + cs_ald2(l)*fdir(k,l)    
          bjch3cocho(3)  = bjch3cocho(3) + cs_ch3cocho(l)*fdir(k,l)
          bjch3ono2(3)   = bjch3ono2(3) + cs_orgn(l)*fdir(k,l)
          bjispd(3)      = bjispd(3) + cs_ispd(l) * fdir(k,l)
          bj_a_acet(3)   = bj_a_acet(3) + cs_ch3coch3(l)*qy_co_col(k,l)*fdir(k,l)
          bj_b_acet(3)   = bj_b_acet(3) + cs_ch3coch3(l)*qy_c2o3_col(k,l)*fdir(k,l)                      
       end do

       ! ================================================================================ 
       !           Tropo band 4                                                      
       ! ================================================================================
       ! temp indep species for this band: hno4,ch3ooh,ald2,orgntr  
       do l = band_start(4),band_end(4)
          bjo1d(4)      = bjo1d(4)+cst_o3_col(k,l)*qy_o1d_col(k,l)*fdir(k,l)
          bjno2(4)      = bjno2(4) + cst_no2_col(k,l)*qy_no2_col(k,l)*fdir(k,l)
          bjh2o2(4)     = bjh2o2(4) + cst_h2o2_col(k,l-17)*fdir(k,l)
          bjhno3(4)     = bjhno3(4) + cst_hno3_col(k,l)*fdir(k,l)
          bjhno4(4)     = bjhno4(4) + cs_hno4(l)*fdir(k,l)
          bjhono(4)     = bjhono(4) + cs_hono(l)*fdir(k,l)
          bjn2o5a(4)    = bjn2o5a(4) + cst_n2o5_col(k,l-17)*fdir(k,l)
          bjcoh2(4)     = bjcoh2(4) + cst_ch2o_col(k,l-17)*qyh2_co(l)*fdir(k,l)
          bjchoh(4)     = bjchoh(4) + cst_ch2o_col(k,l-17)*qyh_hco(l)*fdir(k,l)           
          bjch3ooh(4)   = bjch3ooh(4) + cs_ch3ooh(l)*fdir(k,l)
          bjpana(4)     = bjpana(4) + cst_pan_col(k,l)*qy_pan(l)*fdir(k,l)
          bjpanb(4)     = bjpanb(4) + cst_pan_col(k,l)*(1.0-qy_pan(l))*fdir(k,l)
          bjald2(4)     = bjald2(4) + cs_ald2(l)*fdir(k,l)        
          bjch3cocho(4) = bjch3cocho(4) + cs_ch3cocho(l)*qy_ch3cocho_col(k,l-37)*fdir(k,l)
          bjch3ono2(4)  = bjch3ono2(4) + cs_orgn(l)*fdir(k,l)
          bjispd(4)     = bjispd(4) + cs_ispd(l) * fdir(k,l)
          bj_a_acet(4)  = bj_a_acet(4) + cs_ch3coch3(l)*qy_co_col(k,l)*fdir(k,l)
          bj_b_acet(4)  = bj_b_acet(4) + cs_ch3coch3(l)*qy_c2o3_col(k,l)*fdir(k,l)        
       end do

       ! ======================================================================================== 
       !           Tropo band 5                                                      
       ! ======================================================================================== 
       ! temp indep species for this band: hno4,ch3ooh,ald2,orgntr
       do l = band_start(5),band_end(5)
          bjo1d(5)      = bjo1d(5)+cst_o3_col(k,l)*qy_o1d_col(k,l)*fdir(k,l)
          bjno2(5)      = bjno2(5)+cst_no2_col(k,l)*qy_no2_col(k,l)*fdir(k,l)
          bjh2o2(5)     = bjh2o2(5)+cst_h2o2_col(k,l-17)*fdir(k,l)
          bjhno3(5)     = bjhno3(5)+cst_hno3_col(k,l)*fdir(k,l)
          bjhno4(5)     = bjhno4(5)+cs_hno4(l)*fdir(k,l)
          bjhono(5)     = bjhono(5)+cs_hono(l)*fdir(k,l)
          bjn2o5a(5)    = bjn2o5a(5)+cst_n2o5_col(k,l-17)*fdir(k,l)
          bjcoh2(5)     = bjcoh2(5)+cst_ch2o_col(k,l-17)*qyh2_co(l)*fdir(k,l)
          bjchoh(5)     = bjchoh(5)+cst_ch2o_col(k,l-17)*qyh_hco(l)*fdir(k,l)
          bjch3ooh(5)   = bjch3ooh(5)+cs_ch3ooh(l)*fdir(k,l)
          bjpana(5)     = bjpana(5) + cst_pan_col(k,l)*qy_pan(l)*fdir(k,l)
          bjpanb(5)     = bjpanb(5) + cst_pan_col(k,l)*(1.0-qy_pan(l))*fdir(k,l)
          bjald2(5)     = bjald2(5) + cs_ald2(l)*fdir(k,l)        
          bjch3cocho(5) = bjch3cocho(5)+cs_ch3cocho(l)*qy_ch3cocho_col(k,l-37)*fdir(k,l)
          bjch3ono2(5)  = bjch3ono2(5)+cs_orgn(l)*fdir(k,l)
          bjispd(5)     = bjispd(5) + cs_ispd(l) * fdir(k,l)      
       end do
       !=========================================================================================
       !           Tropo band 6
       !=========================================================================================

       do l = band_start(6),band_end(6)         
          bjno2(6)      = bjno2(6) +cst_no2_col(k,l)*qy_no2_col(k,l)*fdir(k,l)
          bjcoh2(6)     = bjcoh2(6)+cst_ch2o_col(k,l-17)*qyh2_co(l)*fdir(k,l)
          bjch3ooh(6)   = bjch3ooh(6)+cs_ch3ooh(l)*fdir(k,l)
          bjno2o(6)     = bjno2o(6)+cst_no3_col(k,l-60)*qyno2_o(l-60)*fdir(k,l)
          bjch3cocho(6) = bjch3cocho(6)+cs_ch3cocho(l)*qy_ch3cocho_col(k,l-37)*fdir(k,l)
          bjispd(6)     = bjispd(6) + cs_ispd(l) * fdir(k,l)      
       end do

       ! Add the contribution from band 6 separately for H2O2, N2O5 and HNO3 for high angle grid to allow reducion in cst arrays
       ! This has been tested using a box model to ensure that no errors are introduced compared to using main array

       if(zangle>71.) then

          bjh2o2(6)     = bjh2o2(6)+cst_h2o2_col(k,44)*fdir(k,61)
          bjh2o2(6)     = bjh2o2(6)+cst_h2o2_col(k,45)*fdir(k,62)

          do c=63,68
             bjn2o5a(6)    = bjn2o5a(6)+cst_n2o5_col(k,c-17)*fdir(k,c)
          enddo

          bjhno3(6)     = bjhno3(6)+cst_hno3_col(k,63)*fdir(k,63)

          bjpana(6)      = 0.
          bjpanb(6)      = 0.

       elseif(zangle<=71.) then

          do c=61,63
             bjhno3(6)     = bjhno3(6)+cst_hno3_col(k,c)*fdir(k,c)
          enddo

          do c=61,69
             bjn2o5a(6)    = bjn2o5a(6)+cst_n2o5_col(k,c-17)*fdir(k,c)
          enddo

          do c=61,62
             bjpana(6)        = bjpana(6)+cst_pan_col(k,c)*qy_pan(c)*fdir(k,c)
             bjpanb(6)        = bjpanb(6)+cst_pan_col(k,c)*(1.0-qy_pan(c))*fdir(k,c)
          enddo

       endif
       !======================================================================================== 
       !           Tropo band 7                                                      
       !========================================================================================= 

       do l = band_start(7),band_end(7)-2
          bjno2o(7)     = bjno2o(7)+cst_no3_col(k,l-60)*qyno2_o(l-60)*fdir(k,l)
          bjnoo2(7)     = bjnoo2(7)+cst_no3_col(k,l-60)*qyno_o2(l-60)*fdir(k,l)
       end do

       ! only set a scaling ratio for the first band once the sza > 71.
       ! only calculate limits to bands 2 and 4 for high sza         

       if(zangle<=71.) then
          delta1 = fact(k,1)/fdir(k,band_middle(1))
          delta2 = fact(k,2)/fdir(k,band_middle(2))
          delta3 = fact(k,3)/fdir(k,band_middle(3))
          delta4 = fact(k,4)/fdir(k,band_middle(4))
          delta5 = fact(k,5)/fdir(k,band_middle(5))
          delta6 = fact(k,6)/fdir(k,band_middle(6))
          delta7 = fact(k,7)/fdir(k,band_middle(7))
       elseif(zangle>71. .and. zangle<=sza_limit) then
          delta1 = safe_div( fact(k,1), fdir(k,band_middle(1)), huge(1.))
          delta2 = safe_div( fact(k,2), fdir(k,band_middle(2)), huge(1.))
          delta3 = safe_div( fact(k,3), fdir(k,band_middle(3)), huge(1.))
          delta4 = safe_div( fact(k,4), fdir(k,band_middle(4)), huge(1.))
          delta5 = safe_div( fact(k,5), fdir(k,band_middle(5)), huge(1.))
          delta6 = safe_div( fact(k,6), fdir(k,band_middle(6)), huge(1.))
          delta7 = safe_div( fact(k,7), fdir(k,band_middle(7)), huge(1.))
          if(fdir(k,band_middle(1))>5.e9) delta1_spec = fact(k,1)/fdir(k,band_middle(1))           
          if(fdir(k,band_middle(3))>1.e9) delta3_spec = fact(k,3)/fdir(k,band_middle(3))
       endif

       !        ============================================================
       !        CALCULATION PHOTOLYSIS RATES FOR SCATTERING ATMOSPHERE    
       !        ============================================================

       ! O2 -> O3P

       rj(k,jo2)   = bjo2(1)*delta1

       ! O3 -> 2OH 

       rj(k,jo3d)  =  bjo1d(1)*delta1 + bjo1d(2)*delta2 &
            + bjo1d(3)*delta3 + bjo1d(4)*delta4 &
            + bjo1d(5)*delta5

       ! NO2 -> O3

       rj(k,jno2)  = bjno2(1)*delta1 + bjno2(2)*delta2 + &
            bjno2(3)*delta3 + bjno2(4)*delta4 + &
            bjno2(5)*delta5 + bjno2(6)*delta6   

       ! HNO3 -> OH + NO2 

       rj(k,jhno3)  = bjhno3(1)*delta1 + bjhno3(2)*delta2 + &
            bjhno3(3)*delta3 + bjhno3(4)*delta4 + &
            bjhno3(5)*delta5 + bjhno3(6)*delta6

       ! HNO4 -> HO2 + NO2 

       rj(k,jhno4)  =  bjhno4(1)*delta1 + bjhno4(2)*delta2 + &
            bjhno4(3)*delta3 + bjhno4(4)*delta4 + &
            bjhno4(5)*delta5 
            
       ! HONO -> OH + NO
       
       rj(k,jhono)  =  bjhono(1)*delta1 + bjhono(2)*delta2 + &
            bjhono(3)*delta3 + bjhono(4)*delta4 + &
            bjhono(5)*delta5        

       ! N2O5 -> NO3 + NO2                                  
       rj(k,jn2o5a)  =  bjn2o5a(1)*delta1 + bjn2o5a(2)*delta2 +  &
            bjn2o5a(3)*delta3 + bjn2o5a(4)*delta4 +  &
            bjn2o5a(5)*delta5 + bjn2o5a(6)*delta6 
            
       ! N2O5 -> NO3 + NO                                  
       rj(k,jn2o5b)  =  bjn2o5b(1)*delta1 + bjn2o5b(2)*delta2 +  &
            bjn2o5b(3)*delta3       

       ! PAN   -> NO2 + C2O3

       rj(k,jpana) =   bjpana(1)*delta1  + bjpana(2)*delta2 +   &
            bjpana(3)*delta3  + bjpana(4)*delta4 +   &
            bjpana(5)*delta5  + bjpana(6)*delta6
            
       ! PAN   -> NO3 + CH3O2
       
        rj(k,jpanb) =   bjpanb(1)*delta1  + bjpanb(2)*delta2 +   &
            bjpanb(3)*delta3  + bjpanb(4)*delta4 +   &
            bjpanb(5)*delta5  + bjpanb(6)*delta6            

       ! CH2O -> CO

       rj(k,jach2o)  =  bjcoh2(2)*delta2  +  bjcoh2(3)*delta3 &
            + bjcoh2(4)*delta4 +  bjcoh2(5)*delta5 &
            + bjcoh2(6)*delta6   

       ! CH2O -> COH + H

       rj(k,jbch2o) = bjchoh(1)*delta1 + bjchoh(2)*delta2 &
                    + bjchoh(3)*delta3 + bjchoh(4)*delta4 &
                    + bjchoh(5)*delta5 + bjchoh(6)*delta6

       ! H2O2 -> 2OH

       rj(k,jh2o2) = bjh2o2(1)*delta1 + bjh2o2(2)*delta2 &
                   + bjh2o2(3)*delta3 + bjh2o2(4)*delta4 &
                   + bjh2o2(5)*delta5 + bjh2o2(6)*delta6 

       ! NO3 -> NO2 + O

       rj(k,jano3)  = bjno2o(6)*delta6 + bjno2o(7)*delta7

       ! NO3 -> NO

       rj(k,jbno3) = bjnoo2(7)*delta7

       ! CH3OOH -> HCHO + HO2 + OH                                                                        
       rj(k,jmepe) = bjch3ooh(1)*delta1 + bjch3ooh(2)*delta2 + &
                     bjch3ooh(3)*delta3 + bjch3ooh(4)*delta4 + &
                     bjch3ooh(5)*delta5 + bjch3ooh(6)*delta6 

         ! ALD2 -> 2HO2 + CO + CH3O2 
         
       rj(k,jald2) = bjald2(1)*delta1 + bjald2(2)*delta2     + &
                     bjald2(3)*delta3 + bjald2(4)*delta4     + &
                     bjald2(5)*delta5
                 

       ! CH3ONO2 -> HO2 + NO2

       rj(k,jorgn) = bjch3ono2(1)*delta1 + bjch3ono2(2)*delta2 + &
                     bjch3ono2(3)*delta3 + bjch3ono2(4)*delta4 + &
                     bjch3ono2(5)*delta5


       ! CH3COCHO -> C2O3 + HO2 + CO                              
       rj(k,jmgly) = bjch3cocho(2)*delta2 + bjch3cocho(3)*delta3 +  &
                   bjch3cocho(4)*delta4 + bjch3cocho(5)*delta5 + &
                   bjch3cocho(6)*delta6 + bjch3cocho(7)*delta7 
            
       ! ISPD -> 0.333CO + 0.067ALD2 + 0.9CH2O + 0.832PAR + 1.033HO2 + 0.7XO2 + 0.967C2O3
          
       rj(k,jispd) = bjispd(2)*delta2 + bjispd(3)*delta3 + &
                     bjispd(4)*delta4 + bjispd(5)*delta5 + &
                     bjispd(6)*delta6
                       
       !ch3coch3 -> 2CH3O2 + CO
           
       rj(k,ja_acet) =  bj_a_acet(2)*delta2 + bj_a_acet(3)*delta3 + bj_a_acet(4)*delta4
       
       rj(k,jb_acet) = bj_b_acet(2)*delta2 + bj_b_acet(3)*delta3 + bj_b_acet(4)*delta4 

       if(zangle>80. .and. zangle<=85.) then
          
          rj(k,jo3d) = 0. ; rj(k,jhno3) = 0. ; rj(k,jhno4) = 0. ; rj(k,jn2o5a) = 0. ; rj(k,jn2o5b) = 0.
          rj(k,jhono) = 0. ; rj(k,jh2o2) = 0. ; rj(k,jach2o) = 0. ; rj(k,jpana) = 0. ; rj(k,jpanb) = 0.
          rj(k,jald2) = 0. ; rj(k,jorgn) = 0. ; rj(k,jbch2o) = 0. ; rj(k,jmgly) = 0.
          rj(k,jo2) = 0. ; rj(k,jispd) = 0. ; rj(k,ja_acet) = 0. ; rj(k,jb_acet) = 0.

          ! O2 -> 2O3P

          rj(k,jo2) = bjo2(1)*delta1_spec

          ! O3 -> O(1D) + O2                                      
          rj(k,jo3d)  =  bjo1d(1)*delta1_spec + bjo1d(2)*delta2 +   &
                         bjo1d(3)*delta3_spec + bjo1d(4)*delta4 +   &
                         bjo1d(5)*delta5

          ! HNO3 -> OH + NO2                                                                      
          rj(k,jhno3)  = bjhno3(1)*delta1_spec + bjhno3(2)*delta2 + &
                         bjhno3(3)*delta3_spec + bjhno3(4)*delta4 + &
                         bjhno3(5)*delta5      + bjhno3(6)*delta6                 

          ! N2O5 -> NO3 + NO2                                  
          rj(k,jn2o5a)  =  bjn2o5a(1)*delta1_spec + bjn2o5a(2)*delta2 +  &
               bjn2o5a(3)*delta3_spec + bjn2o5a(4)*delta4 +  &
               bjn2o5a(5)*delta5  + bjn2o5a(6)*delta6
               
          ! N2O5 -> NO3 + NO                                  
          rj(k,jn2o5b)  =  bjn2o5b(1)*delta1_spec + bjn2o5b(2)*delta2 +  &
               bjn2o5b(3)*delta3_spec        

          ! PAN 

          rj(k,jpana) = bjpana(1)*delta1_spec + bjpana(2)*delta2 +   &
               bjpana(3)*delta3_spec + bjpana(4)*delta4 +   &
               bjpana(5)*delta5  + bjpana(6)*delta6 
               
          rj(k,jpanb) = bjpanb(1)*delta1_spec + bjpanb(2)*delta2 +   &
               bjpanb(3)*delta3_spec + bjpanb(4)*delta4 +   &
               bjpanb(5)*delta5  + bjpanb(6)*delta6             

          ! ORGNTR -> HO2 + NO2

          rj(k,jorgn) = bjch3ono2(1)*delta1_spec + bjch3ono2(2)*delta2 +   &
               bjch3ono2(3)*delta3_spec + bjch3ono2(4)*delta4 +   &
               bjch3ono2(5)*delta5 

         ! ALD2 -> 2HO2 + CO + CH3O2 

          rj(k,jald2) = bjald2(1)*delta1_spec + bjald2(2)*delta2 + &
                        bjald2(3)*delta3_spec + bjald2(4)*delta4 + &
                        bjald2(5)*delta5
                            
          ! NO2 -> O3

          rj(k,jno2)  =  bjno2(1)*delta1_spec + bjno2(2)*delta2 + &
               bjno2(3)*delta3_spec + bjno2(4)*delta4 + &
               bjno2(5)*delta5 + bjno2(6)*delta6

          ! CH2O -> CO

          rj(k,jach2o)  =  bjcoh2(2)*delta2 + bjcoh2(3)*delta3_spec + &
               bjcoh2(4)*delta4 + bjcoh2(5)*delta5 + &
               bjcoh2(6)*delta6

          ! CH2O -> COH + H

          rj(k,jbch2o)  =  bjchoh(1)*delta1_spec + bjchoh(2)*delta2 + &
               bjchoh(3)*delta3_spec + bjchoh(4)*delta4 + &
               bjchoh(5)*delta5 + bjchoh(6)*delta6

          rj(k,jhno4)  =  bjhno4(1)*delta1_spec + bjhno4(2)*delta2 + &
               bjhno4(3)*delta3_spec + bjhno4(4)*delta4 + &
               bjhno4(5)*delta5
               
          rj(k,jhono)  =  bjhono(1)*delta1_spec + bjhono(2)*delta2 + &
               bjhono(3)*delta3_spec + bjhono(4)*delta4 + &
               bjhono(5)*delta5        

          ! H2O2 -> 2OH                                                                           
          rj(k,jh2o2) = bjh2o2(1)*delta1_spec + bjh2o2(2)*delta2 + &
               bjh2o2(3)*delta3_spec + bjh2o2(4)*delta4 + &
               bjh2o2(5)*delta5 + bjh2o2(6)*delta6

          ! CH3OOH -> HCHO + HO2 + OH                                                                     
          rj(k,jmepe) = bjch3ooh(1)*delta1_spec + bjch3ooh(2)*delta2 + &
               bjch3ooh(3)*delta3_spec + bjch3ooh(4)*delta4 + &
               bjch3ooh(5)*delta5 + bjch3ooh(6)*delta6 

          ! CH3COCHO -> C2O3 + HO2 + CO                                   
          rj(k,jmgly) = bjch3cocho(2)*delta2 + bjch3cocho(3)*delta3_spec +  &
               bjch3cocho(4)*delta4 + bjch3cocho(5)*delta5 +  &
               bjch3cocho(6)*delta6 + bjch3cocho(7)*delta7
                      
          ! ispd -> 0.333CO + 0.067ALD2 + 0.9CH2O + 0.832PAR + 1.033HO2 + 0.7XO2 + 0.967C2O3
          
          rj(k,jispd) = bjispd(2)*delta2 + bjispd(3)*delta3_spec + &
                        bjispd(4)*delta4 + bjispd(5)*delta5 + &
                        bjispd(6)*delta6
                       
          rj(k,ja_acet) = bj_a_acet(2)*delta2 + bj_a_acet(3)*delta3_spec + bj_a_acet(4)*delta4 
                         
          rj(k,jb_acet) = bj_b_acet(2)*delta2 + bj_b_acet(3)*delta3_spec + bj_b_acet(4)*delta4
                
       endif ! sza > 80. 

       rj(k,jrooh) = rj(k,jmepe)
       !
       !  take the upper limit for the photolysis rate i.e. qy=0.05
       !                
       rj(k,jispd) = 0.05*rj(k,jispd)
       !
       ! Two channels of CH3O2NO2 photo-dissociation equal to HNO4 photolysis
       ! Taken from Browne et al, ACP, 2011 
       ! 
        
       rj(k,jmo2no2a) = rj(k,jhno4)
       rj(k,jmo2no2b) = rj(k,jhno4)       
    enddo ! layers          
    

  END SUBROUTINE PHOTORATES_TROPO
  !EOC

  !------------------------------------------------------------------------------
  !                    TM5                                                      !
  !------------------------------------------------------------------------------
  !BOP
  !
  ! !IROUTINE:    PHOTOLYSIS_DONE
  !
  ! !DESCRIPTION: Deallocates photolysis data, and writes photolysis statistics:
  !               output (e.g. monthly) averaged photolysis jo3, jno2 and
  !               surface data of: albedo, cloud-cover, cloud optical thickness 
  !               total ozone
  !\\
  !\\
  ! !INTERFACE:
  !
  SUBROUTINE PHOTOLYSIS_DONE( status )
    !
    ! !USES:
    !
    use dims,            only : im, jm, lm, nregions
    use dims,            only : idatei, idatee
    use global_data,     only : outdir
#ifdef with_hdf4
    use file_hdf,        only : THdfFile, TSds
    use file_hdf,        only : Init, Done, WriteAttribute, Init, Done, WriteData
#endif
    use partools,        only : isRoot
    !
    ! !OUTPUT PARAMETERS:
    !
    integer, intent(out)       ::  status
    !
    ! !REVISION HISTORY: 
    !   21 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
    !
    ! !REMARKS:
    !   (1) Called from SOURCES_SINKS/TRACE_END
    !
    !EOP
    !------------------------------------------------------------------------------
    !BOC

    character(len=*), parameter  ::  rname = mname//'/end_photolysis'

    integer              ::  region
    integer              ::  n 
    integer              ::  k,iret,imr,jmr,lmr
    real, allocatable    ::  average_field(:,:,:), average_field_2d(:,:), average_field_5d(:,:,:,:,:)
#ifdef with_hdf4
    type(THdfFile)       ::  io
    type(TSds)           ::  sds
#endif
    character(len=256)  ::  fname

    ! --- begin --------------------------------

    if (isRoot) then
       write (fname,'(a,"/j_statistics_",i4.4,3i2.2,"_",i4.4,3i2.2,".hdf")') &
            trim(outdir), idatei(1:4), idatee(1:4)
#ifdef with_hdf4
       call Init(io,fname,'create',status)
       IF_ERROR_RETURN(status=1)
#endif
    end if

    
    REG: do region=1,nregions
    
       if(isRoot) then
          imr=im(region)
          jmr=jm(region)
          lmr=lm(region)
       else
          imr=1; jmr=1; lmr=1
       end if

       allocate(average_field(imr,jmr,lmr))

       ! Assume that the nav is the same on all proc
       write (gol,*) 'end_photolysis: j_statistics ', &
            '(region, nj_av, nvo3s_av, ncloud_av)', region,   &
            phot_dat(region)%nj_av, phot_dat(region)%nvo3s_av; call goPr

#ifdef with_hdf4
       !---- 3D fields
       if ( phot_dat(region)%nj_av > 0 ) then

         call gather(dgrid(region), phot_dat(region)%jo3_av, average_field, 0, status)

          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%nj_av
             call Init(Sds,io,'jo3_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','1/s',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if

          call gather(dgrid(region), phot_dat(region)%jno2_av, average_field, 0, status)

          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%nj_av
             call Init(Sds,io,'jno2_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','1/s',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if
           
          call gather(dgrid(region), phot_dat(region)%jhno2_av, average_field, 0, status)

          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%nj_av
             call Init(Sds,io,'jhno2_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','1/s',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if
          
          call gather(dgrid(region), phot_dat(region)%jch2oa_av, average_field, 0, status)

          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%nj_av
             call Init(Sds,io,'jch2oa_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','1/s',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if
          
          call gather(dgrid(region), phot_dat(region)%jch2ob_av, average_field, 0, status)

          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%nj_av
             call Init(Sds,io,'jch2ob_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','1/s',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if                  

          call gather(dgrid(region), phot_dat(region)%reff_av, average_field, 0, status)

          if ( isRoot ) then
             call Init(Sds,io,'reff_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','um',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if

          call gather(dgrid(region), phot_dat(region)%lwp_av, average_field, 0, status)

          if ( isRoot ) then
             call Init(Sds,io,'lwp_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','g/m2',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if
       end if
       
       ! ---- 2D fields
       if ( phot_dat(region)%nalb_av > 0 ) then

          allocate(average_field_2d(imr,jmr))

          call gather(dgrid(region), phot_dat(region)%ags_av, average_field_2d, 0, status)

          if(isRoot) then
             average_field_2d = average_field_2d / phot_dat(region)%nalb_av
             call Init(Sds,io,'ags_av',(/imr,jmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','Fraction',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field_2d,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if


          call gather(dgrid(region), phot_dat(region)%sza_av, average_field_2d, 0, status)

          if ( isRoot ) then
             average_field_2d = average_field_2d / phot_dat(region)%nalb_av
             call Init(Sds,io,'sza_av',(/imr,jmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','Zenith Angle',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field_2d,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if

          deallocate(average_field_2d)

       end if ! any 2D field
       

       ! Clouds data (3D)
       if ( phot_dat(region)%ncloud_av > 0 ) then

          call gather(dgrid(region), phot_dat(region)%pmcld_av, average_field, 0, status)

          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%ncloud_av
             call Init(Sds,io,'pmcld_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit',' ',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          endif
          
          call gather(dgrid(region), phot_dat(region)%taus_cld_av, average_field, 0, status)

          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%ncloud_av
             call Init(Sds,io,'taus_cld_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit',' ',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if

          call gather(dgrid(region), phot_dat(region)%taua_cld_av, average_field, 0, status)

          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%ncloud_av
             call Init(Sds,io,'taua_cld_av',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit',' ',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if

       end if

       ! Aerosols info (5D)
       if ( phot_dat(region)%naer_av > 0 ) then

          allocate(average_field_5d(imr,jmr,lmr,nbands_trop,ngrid))

          call gather(dgrid(region), phot_dat(region)%pmaer_av, average_field_5d, 0, status)

          if ( isRoot ) then
             average_field_5d = average_field_5d/phot_dat(region)%naer_av
             call Init(Sds,io,'pmaer_av',(/imr,jmr,lmr,nbands_trop,ngrid/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit',' ',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field_5d,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if

          call gather(dgrid(region), phot_dat(region)%taus_aer_av, average_field_5d, 0, status)

          if ( isRoot ) then
             average_field_5d = average_field_5d/phot_dat(region)%naer_av
             call Init(Sds,io,'taus_aer_av',(/imr,jmr,lmr,nbands_trop,ngrid/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit',' ',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field_5d,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if

          call gather(dgrid(region), phot_dat(region)%taua_aer_av, average_field_5d, 0, status)

          if ( isRoot ) then
             average_field_5d = average_field_5d/phot_dat(region)%naer_av
             call Init(Sds,io,'taua_aer_av',(/imr,jmr,lmr,nbands_trop,ngrid/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit',' ',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field_5d,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          end if
          
          deallocate(average_field_5d)
       end if



       if ( phot_dat(region)%nsad_av >0 ) then
  
          call gather(dgrid(region), phot_dat(region)%sad_cld_av, average_field, 0, status)
          
          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%nsad_av
             call Init(Sds,io,'sad_cld',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','cm^2/cm^3 ',status)
             call WriteAttribute(Sds,'long_name','average water cloud surface area density',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          endif
          
          call gather(dgrid(region), phot_dat(region)%sad_ice_av, average_field, 0, status)
          
          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%nsad_av
             call Init(Sds,io,'sad_ice',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','cm^2/cm^3 ',status)
             call WriteAttribute(Sds,'long_name','average ice cloud surface area density',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          endif
          
          call gather(dgrid(region), phot_dat(region)%sad_aer_av, average_field, 0, status)

          if ( isRoot ) then
             average_field = average_field/phot_dat(region)%nsad_av
             call Init(Sds,io,'sad_aer',(/imr,jmr,lmr/),'real(4)',status)
             IF_ERROR_RETURN(status=1)
             call WriteAttribute(Sds,'Unit','cm^2/cm^3 ',status)
             call WriteAttribute(Sds,'long_name','average aerosol surface area density',status)
             IF_ERROR_RETURN(status=1)
             call WriteData(Sds,average_field,status)
             IF_ERROR_RETURN(status=1)
             call Done(Sds,status)
             IF_ERROR_RETURN(status=1)
          endif
       end if
#endif
       
       deallocate(average_field)

    end do REG

#ifdef with_hdf4    
    if ( isRoot ) then
       call Done(io, status)
       IF_ERROR_RETURN(status=1)
    endif
#endif
    
    do region = 1,nregions

       if (associated( phot_dat(region)%o3klim_top)) deallocate(phot_dat(region)%o3klim_top )
       deallocate(phot_dat(region)%albedo     )       
       deallocate(phot_dat(region)%aero_surface_clim)            
       deallocate(phot_dat(region)%cloud_reff )
       deallocate(phot_dat(region)%pmcld      )
       deallocate(phot_dat(region)%taus_cld   )
       deallocate(phot_dat(region)%taua_cld   )
       deallocate(phot_dat(region)%pmaer      )
       deallocate(phot_dat(region)%taus_aer   )
       deallocate(phot_dat(region)%taua_aer   )
       deallocate(phot_dat(region)%lwp_av     )
       deallocate(phot_dat(region)%cfr_av     )
       deallocate(phot_dat(region)%reff_av    )
       deallocate(phot_dat(region)%ags_av     )
       deallocate(phot_dat(region)%sza_av     )
       deallocate(phot_dat(region)%jo3        )
       deallocate(phot_dat(region)%jno2       )
       deallocate(phot_dat(region)%jhno2      )
       deallocate(phot_dat(region)%jch2oa     )
       deallocate(phot_dat(region)%jch2ob     )
       deallocate(phot_dat(region)%jo3_av     )
       deallocate(phot_dat(region)%jno2_av    )
       deallocate(phot_dat(region)%jhno2_av   )
       deallocate(phot_dat(region)%jch2oa_av  )
       deallocate(phot_dat(region)%jch2ob_av  )
       
       deallocate(phot_dat(region)%taua_aer_av)
       deallocate(phot_dat(region)%taus_aer_av)
       deallocate(phot_dat(region)%pmaer_av   )
       deallocate(phot_dat(region)%taua_cld_av)
       deallocate(phot_dat(region)%taus_cld_av)
       deallocate(phot_dat(region)%pmcld_av   )
       deallocate(phot_dat(region)%v2         )
       deallocate(phot_dat(region)%v3         )
       deallocate(phot_dat(region)%v3_surf    )
       deallocate(phot_dat(region)%qy_ch3cocho)
       deallocate(phot_dat(region)%qy_c2o3    )
       deallocate(phot_dat(region)%sad_cld    )
       deallocate(phot_dat(region)%sad_ice    )
       deallocate(phot_dat(region)%sad_aer    )
       deallocate(phot_dat(region)%sad_cld_av )
       deallocate(phot_dat(region)%sad_ice_av )
       deallocate(phot_dat(region)%sad_aer_av )

    end do

#ifdef with_optics
     deallocate( wdep )  !NB optics_done
#endif
    ! ok
    status = 0 

  END SUBROUTINE PHOTOLYSIS_DONE
  !EOC

END MODULE PHOTOLYSIS
