!-------------------------------------------------------------------------
!  NASA/GFSC, SIVO, Code 610.3
!-------------------------------------------------------------------------
!BOP
!
! !MODULE: FastJX53cCoreFastj_mod
!
! !INTERFACE:
!

      module FastJX53cCoreFastj_mod 3
!
      implicit none
!
! !PUBLIC MEMBER FUNCTIONS:
!
      private
      public  :: JRATET
      public  :: JP_ATM
      public  :: RD_XXX
      public  :: RD_MIE
      public  :: FLINT
      public  :: SOLARZ
      public  :: SPHERE
      public  :: EXTRAL
      public  :: OPMIE
!
! !DESCRIPTION:
! Contains core fast-J routines.
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
      CONTAINS
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: JRATET
!
! !INTERFACE:
!

      subroutine JRATET(PPJ,TTJ,FFF, VALJL) 3,15
!
! !USES:
      use FastJX53cJvaluesVars_mod  , only : NJVAL, TQQ, QO2, QO3, Q1D, TITLEJ
      use FastJX53cJvaluesVars_mod  , only : NW1, NW2, QQQ
      use FastJX53cCTMparameters_mod, only : L1_, W_, JVL_, X_

      implicit none
!
! !INPUT PARAMETERS:
      real*8, intent(in)  :: PPJ(L1_+1)        ! pressure profile at edges
      real*8, intent(in)  :: TTJ(L1_)          ! temperatures at mid-level
      real*8, intent(in)  :: FFF(W_,JVL_)      ! mean actinic flux
!
! !OUTPUT PARAMETERS:
      real*8, intent(out) :: VALJL(JVL_,NJVAL) ! JVL_ = no of levels
!
! !DESCRIPTION:
!  Calculate J-value, called by PTOTOJ.
!
! !LOCAL VARIABLES:
      real*8  VALJ(X_)          ! temp for call J's at one L
      real*8  QO2TOT, QO3TOT, QO31DY, QO31D, QQQT, TFACT
      real*8  TT,PP,DD,TT200,TFACA,TFAC0,TFAC1,TFAC2,QQQA,QQ2,QQ1A,QQ1B
      integer J,K,L, IV
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
!BOC
      do L = 1,JVL_    ! master loop over layer = L

!---need temperature and density (for some quantum yields):
!---in this case the Pressures PPJ are defined at the boundaries,
!---                Temperatures in the middle of each layer
        TT   = TTJ(L)
        PP  = (PPJ(L)+PPJ(L+1))*0.5d0
          if (L.eq.1) PP = PPJ(1)
        DD = 7.24e18*PP/TT

        do J = 1,NJVAL
          VALJ(J) = 0.d0
        enddo

        do K = NW1,NW2                    ! Using model 'T's here
           QO3TOT = FLINT(TT,TQQ(1,2),TQQ(2,2),TQQ(3,2) &
     &                       ,QO3(K,1),QO3(K,2),QO3(K,3))
           QO2TOT = FLINT(TT,TQQ(1,1),TQQ(2,1),TQQ(3,1) &
     &                       ,QO2(K,1),QO2(K,2),QO2(K,3))
           QO31DY = FLINT(TT,TQQ(1,3),TQQ(2,3),TQQ(3,3) &
     &                       ,Q1D(K,1),Q1D(K,2),Q1D(K,3))
           QO31D  = QO31DY*QO3TOT
          VALJ(1) = VALJ(1) + QO2TOT*FFF(K,L)
          VALJ(2) = VALJ(2) + QO3TOT*FFF(K,L)
          VALJ(3) = VALJ(3) + QO31D*FFF(K,L)
        enddo
        VALJ(2) = VALJ(2) - VALJ(3) ! Kouatchou To see if O3 -> O(3P)+O2 will be close to from previous fastj versions

        do J = 4,NJVAL

          if (TQQ(2,J) .gt. TQQ(1,J)) then
           TFACT = max(0.d0,min(1.d0,(TT-TQQ(1,J))/(TQQ(2,J)-TQQ(1,J))))
          else
           TFACT = 0.d0
          endif

          do K = NW1,NW2
            QQQT    = QQQ(K,1,J) + (QQQ(K,2,J) - QQQ(K,1,J))*TFACT
            VALJ(J) = VALJ(J) + QQQT*FFF(K,L)
          enddo

! #52 Methylvinyl ketone   'MeVK  '     q(M) = 1/(1 + 1.67e-19*[M])
          if (TITLEJ(J).eq.'MeVK  ') then
            VALJ(J) = VALJ(J)/(1.0 + 1.67e-19*DD)
          endif
! #55 Methylethyl ketone   MEKeto     q(M) = 1/(1 + 2.0*[M/2.5e19])
          if (TITLEJ(J).eq.'MEKeto') then
            VALJ(J) = VALJ(J)/(1.0 + 0.80E-19*DD)
          endif
! #57 Methyl glyoxal       MGlyxl     q(M) = 1/(1 + 4.15*[M/2.5E19])
          if (TITLEJ(J).eq.'MGlyxl') then
            VALJ(J) = VALJ(J)/(1.0 + 1.66e-19*DD)
          endif

        enddo

      if (TITLEJ(NJVAL-1).eq.'Acet-a') then
!--------------J-ref v8.3 includes Blitz ACETONE q-yields--------------
!---Acetone is a special case:   (as per Blitz et al GRL, 2004)
!---     61 = NJVAL-1 = J1(acetone-a) ==> CH3CO + CH3
!---     62 = NJVAL   = J2(acetone-b) ==> CH3 + CO + CH3
          VALJ(NJVAL-1) = 0.d0
          VALJ(NJVAL)   = 0.d0
!---IV=NJVAL-1 = Xsect (total abs) for Acetone - pre-calc Temp interp factors
        IV    = NJVAL-1
        TFACA = (TT-TQQ(1,IV))/(TQQ(2,IV)-TQQ(1,IV))
        TFACA = max(0.d0, min(1.d0, TFACA))
!---IV=NJVAL = Q2 for Acetone=>(2), specifically designed for quadratic interp.
!---      but force to Q2=0 by 210K
        IV    = NJVAL
        TFAC0 = ( (TT-TQQ(1,IV))/(TQQ(2,IV)-TQQ(1,IV)) )**2
        if (TT .lt. TQQ(1,IV)) then
          TFAC0 = (TT - 210.d0)/(TQQ(1,IV)-210.d0)
        endif
        TFAC0 = max(0.d0, min(1.d0, TFAC0))
!---IV=NJVAL+1 = Q1A for Acetone => (1), allow full range of T = 200K-300K
        IV    = NJVAL+1
        TT200 = min(300.d0, max(200.d0, TT))
        TFAC1 = (TT200-TQQ(1,IV))/(TQQ(2,IV)-TQQ(1,IV))
!---IV=NJVAL+2 = Q1B for Acetone => (1)
        IV    = NJVAL+2
        TFAC2 = (TT200-TQQ(1,IV))/(TQQ(2,IV)-TQQ(1,IV))

!---now integrate over wavelengths
        do K = NW1,NW2
!---NJVAL-1 = Xsect (total abs) for Acetone
          IV   = NJVAL-1
          QQQA = QQQ(K,1,IV) + (QQQ(K,2,IV)-QQQ(K,1,IV))*TFACA
!---NJVAL   = Q2 for Acetone=>(2), specifically designed for quadratic interp.
          IV   = NJVAL
          QQ2  = QQQ(K,1,IV) + (QQQ(K,2,IV)-QQQ(K,1,IV))*TFAC0
          if (TT .lt. TQQ(1,IV)) then
            QQ2 = QQQ(K,1,IV)*TFAC0
          endif
!---NJVAL+1 = Q1A for Acetone => (1), allow full range of T = 200K-300K
          IV   = NJVAL+1
          QQ1A = QQQ(K,1,IV) + (QQQ(K,2,IV)-QQQ(K,1,IV))*TFAC1
!---NJVAL+2 = Q1B for Acetone => (1)   ! scaled to [M]=2.5e19
          IV   = NJVAL+2
          QQ1B = QQQ(K,1,IV) + (QQQ(K,2,IV)-QQQ(K,1,IV))*TFAC2
          QQ1B = QQ1B*4.d-20
!---J(61)
          VALJ(NJVAL-1) = VALJ(NJVAL-1) &
     &         + FFF(K,L)*QQQA*(1.d0-QQ2)/(QQ1A + QQ1B*DD)
!---J(62)
          VALJ(NJVAL) = VALJ(NJVAL) + FFF(K,L)*QQQA*QQ2

        enddo    !K
!-----------end v-8.3 includes Blitz ACETONE q-yields--------------
      endif

!----Load array of J-values in native order, need to be indexed/scaled
!    by ASAD-related code later: ZPJ(L,JJ) = VALJL(L,JIND(JJ))*JFACTA(JJ)
        do J=1,NJVAL
          VALJL(L,J) = VALJ(J)
        enddo

      enddo    ! master loop over L=1,JVL_
      return
      end subroutine JRATET
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: JP_ATM
!
! !INTERFACE:
!

      subroutine JP_ATM(PPJ,TTJ,DDJ,ZZJ,ZHL,ZZHT,AER,ABX,ADX,JXTRA) 3,2
!
! !USES:
!
      use FastJX53cCTMparameters_mod, only : L1_, L2_
!
      implicit none
!
! !INPUT PARAMETERS:
!--------key amtospheric data needed to solve plane-parallel J---------
      real*8, dimension(5,L1_) :: AER
      integer,dimension(5,L1_) :: ADX
      real*8, dimension(L1_)   :: ABX, TTJ,DDJ,ZZJ,ZHL
      real*8, dimension(L1_+1) :: PPJ 
      integer,dimension(L2_+1) :: JXTRA
      real*8                   :: ZZHT
!
! !DESCRIPTION:
!  print out atmosphere used in J-value calc.
!
! !LOCAL VARIABLES:
      integer  I,J,K,L
      real*8   COL(4),COLO2,COLO3,ZKM,DELZ,ZTOP
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
!BOC
        write(6,100)
  100 format('   L z(km)     p      T   ','    d(air)   d(O3)', &
     & '  col(O2)  col(O3)   ndx  col(aer/cld)')

          COLO2 = 0.d0
          COLO3 = 0.d0
         do I=1,4
          COL(I) = 0.d0
         enddo
          ZTOP = ZHL(L1_) + ZZHT

        do L = L1_,1,-1

          do I=1,4
          COL(I) = COL(I) + AER(I,L)
          enddo
          COLO2 = COLO2 + DDJ(L)*0.20948d0  
          COLO3 = COLO3 + ZZJ(L)
          DELZ = ZTOP-ZHL(L)
          ZTOP = ZHL(L)
          ZKM = ZHL(L)*1.d-5

        write(6,110) L,ZKM,PPJ(L),TTJ(L),DDJ(L)/DELZ,ZZJ(L)/DELZ, &
     &       COLO2,COLO3, &
     &      (ADX(I,L),COL(I), I=1,4), JXTRA(L+L),JXTRA(L+L-1)
  110 format(1x,i3,0p,f6.2,f10.3,f7.2,1p,4e9.2,4(i3,e9.2),2i3)

        enddo

      return
      end subroutine JP_ATM
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: RD_XXX
!
! !INTERFACE:
!

      subroutine RD_XXX(NJ1,NAMFIL) 3,12
!
! !USES:
      use FastJX53cCTMparameters_mod, only : X_
      use FastJX53cJvaluesVars_mod  , only : TQQ   , QQQ   , QRAYL
      use FastJX53cJvaluesVars_mod  , only : QO2   , QO3   , Q1D
      use FastJX53cJvaluesVars_mod  , only : WBIN  , WL    , FL 
      use FastJX53cJvaluesVars_mod  , only : NJVAL , NW1   , NW2
      use FastJX53cJvaluesVars_mod  , only : TITLE0, TITLEJ, TITLEJ2, TITLEJ3
!
      implicit none
!
! !INPUT PARAMETERS:
      integer     , intent(in) :: NJ1
      character(*), intent(in) ::  NAMFIL
!
! !DESCRIPTION:
!  Read in wavelength bins, solar fluxes, Rayleigh parameters, 
!      T-dependent X-sections. 
! \newline
!  {\bf Current code revised to JPL-02 ver 8.5 (5/05)}
! \newline
!
! \begin{verbatim}
!     NAMFIL   Name of spectral data file (j2_spec.dat) >> j2 for fast-J2
!     NJ1      Channel number for reading data file
!
!     NJVAL    Number of species to calculate J-values for
!     NWWW     Number of wavelength bins, from 1:NWWW
!     WBIN     Boundaries of wavelength bins
!     WL       Centres of wavelength bins - 'effective wavelength'
!     FL       Solar flux incident on top of atmosphere (cm-2.s-1)
!     QRAYL    Rayleigh parameters (effective cross-section) (cm2)
!     QO2      O2 cross-sections
!     QO3      O3 cross-sections
!     Q1D      O3 => O(1D) quantum yield
!     TQQ      Temperature for supplied cross sections
!     QQQ      Supplied cross sections in each wavelength bin (cm2)
! \end{verbatim}
!
! !LOCAL VARIABLES:
      integer  I, J, K, IW, NQQQ, NWWW
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
!BOC

      TQQ(:,:) = 0.d0

!----------spectral data----set for new format data J-ver8.3------------------
!         note that NJVAL = # J-values, but NQQQ (>NJVAL) = # Xsects read in
!         for 2005a data, NJVAL = 62 (including a spare XXXX) and 
!              NQQQ = 64 so that 4 wavelength datasets read in for acetone
!         note NQQQ is not used outside this subroutine!

      open (NJ1,FILE=NAMFIL,status='old',form='formatted')
      read (NJ1,100) TITLE0
      read (NJ1,101) NJVAL,NQQQ, NWWW,NW1,NW2
      if (NJVAL.gt.X_ .or. NQQQ.gt.X_) then
        write(6,201) NJVAL,X_
        stop
      endif
!      write(6,'(1X,A)') TITLE0
!----J-values:  1=O2, 2=O3P,3=O3D 4=readin Xsects
      read (NJ1,102) (WL(IW),IW=1,NWWW)
      read (NJ1,102) (FL(IW),IW=1,NWWW)
      read (NJ1,102) (QRAYL(IW),IW=1,NWWW)

!---Read O2 X-sects, O3 X-sects, O3=>O(1D) quant yields (each at 3 temps)
      read (NJ1,103) TITLEJ(1),TQQ(1,1), (QO2(IW,1),IW=1,NWWW)
      read (NJ1,103) TITLEJ2,  TQQ(2,1), (QO2(IW,2),IW=1,NWWW)
      read (NJ1,103) TITLEJ3,  TQQ(3,1), (QO2(IW,3),IW=1,NWWW)

      read (NJ1,103) TITLEJ(2),TQQ(1,2), (QO3(IW,1),IW=1,NWWW)
      read (NJ1,103) TITLEJ2,  TQQ(2,2), (QO3(IW,2),IW=1,NWWW)
      read (NJ1,103) TITLEJ3,  TQQ(3,2), (QO3(IW,3),IW=1,NWWW)

      read (NJ1,103) TITLEJ(3),TQQ(1,3), (Q1D(IW,1),IW=1,NWWW)
      read (NJ1,103) TITLEJ2,  TQQ(2,3), (Q1D(IW,2),IW=1,NWWW)
      read (NJ1,103) TITLEJ3,  TQQ(3,3), (Q1D(IW,3),IW=1,NWWW)

!      do J = 1,3
!        write(6,200) TITLEJ(J),(TQQ(I,J),I=1,3)
!      enddo

!---Read remaining species:  X-sections at 2 T_s
      do J = 4,NQQQ
        read (NJ1,103) TITLEJ(J),TQQ(1,J),(QQQ(IW,1,J),IW=1,NWWW)
        read (NJ1,103) TITLEJ2,  TQQ(2,J),(QQQ(IW,2,J),IW=1,NWWW)
!          write(6,200) TITLEJ(J),(TQQ(I,J),I=1,2)
      enddo

!  Reset the titles for NJVAL-1 & NJVAL to be the two acetone J_s
!   61: C3H6O  = Acet-a     (CH3CO + CH3) 
!   62: Q2-Ac  = Acet-b     (CH3 + CO + CH3)

      TITLEJ(NJVAL-1) = 'Acet-a'
      TITLEJ(NJVAL)   = 'Acet-b'
      
      close(NJ1)
      
  100 format(a)
  101 format(10x,5i5)
  102 format(10x,    6e10.3/(10x,6e10.3)/(10x,6e10.3))
  103 format(a7,f3.0,6e10.3/(10x,6e10.3)/(10x,6e10.3))
  200 format(1x,' x-sect:',a10,3(3x,f6.2))
  201 format(' Number of x-sections supplied to Fast-J2: ',i3,/, &
     &       ' Maximum number allowed (X_) only set to: ',i3, &
     &       ' - increase in cmn_jv.f')

      return
      end subroutine RD_XXX
!EOC      
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: RD_MIE
!
! !INTERFACE:
!

      subroutine RD_MIE(NJ1,NAMFIL) 3,6
!
! !USES:
!
      use FastJX53cJvaluesVars_mod  , only : NAA, QAA, WAA, PAA, RAA, SSA
      use FastJX53cJvaluesVars_mod  , only : JTAUMX, ATAU, ATAU0
      use FastJX53cJvaluesVars_mod  , only : TITLE0, TITLEA

      implicit none
!
! !INPUT PARAMETERS:
      integer     , intent(in) :: NJ1
      character(*), intent(in) ::  NAMFIL
!
! !DESCRIPTION:
!  Aerosols/cloud scattering data set for fast-JX (ver 5.3).
!  \newline
!  {\bf Spectral data rev to J-ref ver8.5 (5/05)}
!
!  \begin{verbatim}
!     NAMFIL   Name of scattering data file (e.g., FJX_scat.dat)
!     NJ1      Channel number for reading data file
!     NAA      Number of categories for scattering phase functions
!     QAA      Aerosol scattering phase functions
!     NK       Number of wavelengths at which functions supplied (set as 4)
!     WAA      Wavelengths for the NK supplied phase functions
!     PAA      Phase function: first 8 terms of expansion
!     RAA      Effective radius associated with aerosol type
!     SSA      Single scattering albedo
!  \end{verbatim}
!
! !LOCAL VARIABLES:
      integer  I, J, K
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
!BOC
      open (NJ1,FILE=NAMFIL,status='old',form='formatted')

      read (NJ1,'(i2,a78)') NAA,TITLE0
      read (NJ1,'(5x,i5,2f10.5)') JTAUMX,ATAU,ATAU0
!        write(6,'(a,2f9.5,i5)') ' ATAU/ATAU0/JMX',ATAU,ATAU0,JTAUMX
      read (NJ1,*)
      
      do J = 1,NAA
          read (NJ1,'(3x,a20)') TITLEA(J)
        do K = 1,4     ! Fix number of aerosol wavelengths at 4 
          read (NJ1,'(f5.0,f8.1,f7.3,f8.4,f7.3,7f6.3)')  &
     &      WAA(K,J),QAA(K,J),RAA(K,J),SSA(K,J),(PAA(I,K,J),I=1,8)
        enddo
      enddo

      close(NJ1)

!        write(6,*) 'Aerosol phase functions & wavelengths'
!        write(6,*) TITLE0
!      do J=1,NAA
!        write(6,'(1x,A8,I2,A,9F8.1)') &
!     &                   TITLEA(J),J,'  wavel=',(WAA(K,J),K=1,4)
!        write(6,'(9x,I2,A,9F8.4)') J,'  Qext =',(QAA(K,J),K=1,4)
!      enddo

      return
      end subroutine RD_MIE
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !IFUNCTION: FLINT
!
! !INTERFACE:
!

      real*8 FUNCTION FLINT (TINT,T1,T2,T3,F1,F2,F3) 15
!
      implicit none
!
! !INPUT PARAMETERS:
      real*8  TINT,T1,T2,T3,F1,F2,F3
!
! !DESCRIPTION:
!  Three-point linear interpolation function
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
!BOC
      if (TINT .le. T2)  then
        if (TINT .le. T1)  then
          FLINT = F1
        else
          FLINT = F1 + (F2 - F1)*(TINT -T1)/(T2 -T1)
        endif
      else
        if (TINT .ge. T3)  then
          FLINT = F3
        else
          FLINT = F2 + (F3 - F2)*(TINT -T2)/(T3 -T2)
        endif
      endif
      return
      end FUNCTION FLINT
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: SOLARZ
!
! !INTERFACE:
!

      subroutine SOLARZ(GMTIME,NDAY,YGRDJ,XGRDI, SZA,COSSZA,SOLFX) 3
!
      implicit none
!
! !INPUT PARAMETERS:
      real*8, intent(in) ::   GMTIME,YGRDJ,XGRDI
      integer, intent(in) ::  NDAY
!
! !OUTPUT PARAMETERS:
      real*8, intent(out) ::  SZA,COSSZA,SOLFX
!
! !DESCRIPTION:
!  Calculate the Solar Zenith Angle and Solar Flux factor for given 
!  lat/lon/UT.
!  \begin{verbatim}
!     GMTIME = UT for when J-values are wanted 
!           (for implicit solver this is at the end of the time step)
!     NDAY   = integer day of the year (used for solar lat and declin)
!     YGRDJ  = laitude (radians) for grid (I,J)
!     XGDRI  = longitude (radians) for grid (I,J)
!
!     SZA = solar zenith angle in degrees
!     COSSZA = U0 = cos(SZA)
!  \end{verbatim}
!
! !LOCAL VARIABLES:
      real*8  PI, PI180, LOCT
      real*8  SINDEC, SOLDEK, COSDEC, SINLAT, SOLLAT, COSLAT, COSZ
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
!BOC
!
      PI     = 3.141592653589793d0
      PI180  = PI/180.d0
      SINDEC = 0.3978d0*sin(0.9863d0*(dble(NDAY)-80.d0)*PI180)
      SOLDEK = asin(SINDEC)
      COSDEC = cos(SOLDEK)
      SINLAT = sin(YGRDJ)
      SOLLAT = asin(SINLAT)
      COSLAT = cos(SOLLAT)
!
      LOCT   = (((GMTIME)*15.d0)-180.d0)*PI180 + XGRDI
      COSSZA = COSDEC*COSLAT*cos(LOCT) + SINDEC*SINLAT
      SZA    = acos(COSSZA)/PI180

      SOLFX  = 1.d0-(0.034d0*cos(dble(NDAY-186)*2.d0*PI/365.d0))

      return
      end subroutine SOLARZ
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: SPHERE
!
! !INTERFACE:
!

      subroutine SPHERE(GMU,RAD,ZHL,ZZHT,AMF,L1_) 3
!
      implicit none
!
! !INPUT PARAMETERS:
      integer, intent(in)  :: L1_      ! dimension of CTM = levels +1
      real*8 , intent(in)  :: GMU      ! MU0 = cos(solar zenith angle)
      real*8 , intent(in)  :: RAD      ! radius of Earth mean sea level (cm)
      real*8 , intent(in)  :: ZHL(L1_) ! height (cm) of the bottome edge of CTM level L1_
      real*8 , intent(in)  :: ZZHT     ! scale height (cm) used above top of CTM (ZHL(L_+1)
!
! !OUTPUT PARAMETERS:
      real*8 , intent(out) :: AMF(L1_,L1_) 
                           ! air mass factor for CTM level I for sunlight reaching J
!
! !DESCRIPTION:
!  Calculation of spherical geometry; derive tangent heights, slant path
!  lengths and air mass factor for each layer. Not called when
!  $SZA \;\; > \;\; 98$ degrees.  Beyond 90 degrees, include treatment 
!  of emergent  beam (where tangent height is below altitude J-value 
!  desired at).
!
! !LOCAL VARIABLES:
      integer  I, J, K, II
      real*8   AIRMAS
      real*8   XMU1, XMU2
      real*8   DIFF, Ux
      real*8   H, ZBYR
      real*8   RZ(L1_)   ! Distance from centre of Earth to each point (cm)
      real*8   RQ(L1_)   ! Square of radius ratios
      real*8   TANHT     ! Tangent height for the current SZA
      real*8   XL        ! Slant path between points
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
!BOC
!
!  Inlined air mass factor function for top of atmosphere
      AIRMAS(Ux,H) = (1.0d0+H)/SQRT(Ux*Ux+2.0d0*H*(1.0d0- &
     &         0.6817d0*EXP(-57.3d0*abs(Ux)/SQRT(1.0d0+5500.d0*H))/ &
     &                                             (1.0d0+0.625d0*H)))
!
      RZ(1) = RAD + ZHL(1)
      ZBYR  = ZZHT/RAD
      do II = 2,L1_
        RZ(II)   = RAD + ZHL(II)
        RQ(II-1) = (RZ(II-1)/RZ(II))**2
      enddo
      if (GMU .lt. 0.0d0)  then
        TANHT = RZ(1)/dsqrt(1.0d0-GMU**2)
      else
        TANHT = RZ(1)
      endif
!
!  Go up from the surface calculating the slant paths between each level
!  and the level above, and deriving the appropriate Air Mass Factor
      do 16 J = 1,L1_
        do I = 1,L1_
          AMF(I,J) = 0.d0
        enddo
!
!  Air Mass Factors all zero if below the tangent height
        if (RZ(J) .lt. TANHT) goto 16
!  Ascend from layer J calculating AMFs
        XMU1 = abs(GMU)
        do I = J,L1_-1
          XMU2     = dsqrt(1.0d0 - RQ(I)*(1.0d0-XMU1**2))
          XL       = RZ(I+1)*XMU2 - RZ(I)*XMU1
          AMF(I,J) = XL / (RZ(I+1)-RZ(I))
          XMU1     = XMU2
        enddo
!  Use function and scale height to provide AMF above top of model
        AMF(L1_,J)  = AIRMAS(XMU1,ZBYR)
!
!  Twilight case - Emergent Beam
        if (GMU .ge. 0.0d0) goto 16
        XMU1       = abs(GMU)
!  Descend from layer J
        do II = J-1,1,-1
          DIFF        = RZ(II+1)*sqrt(1.0d0-XMU1**2)-RZ(II)
          if (II.eq.1)  DIFF = max(DIFF,0.d0)   ! filter
!  Tangent height below current level - beam passes through twice
          if (DIFF .lt. 0.0d0)  then
            XMU2      = sqrt(1.0d0 - (1.0d0-XMU1**2)/RQ(II))
            XL        = abs(RZ(II+1)*XMU1-RZ(II)*XMU2)
            AMF(II,J) = 2.d0*XL/(RZ(II+1)-RZ(II))
            XMU1      = XMU2
!  Lowest level intersected by emergent beam
          else
            XL        = RZ(II+1)*XMU1*2.0d0
            AMF(II,J) = XL/(RZ(II+1)-RZ(II))
            goto 16
          endif
        enddo

   16 continue
      return
      end subroutine SPHERE
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: EXTRAL
!
! !INTERFACE:
!

      subroutine EXTRAL(AER,ADX,L1X,L2X,NX,JTAUMX,ATAU,ATAU0, JXTRA) 3
!
      implicit none
!
      integer, intent(in) ::  JTAUMX,L1X,L2X  !index of cloud/aerosol
      integer, intent(in) ::  NX              !Mie scattering array size
      real*8,  intent(in) ::  AER(5,L1X)      !cloud+3aerosol OD in each layer
      real*8,  intent(in) ::  ATAU,ATAU0
      integer, intent(in) ::  ADX(5,L1X)      !index of cloud/aerosol
      integer, intent(out) ::  JXTRA(L2X+1)   !number of sub-layers to be added
!
! !DESCRIPTION:
!    New version 5.3, add sub-layers (JXTRA) to thick cloud/aerosol layers.
!    This version sets up log-spaced sub-layers of increasing thickness ATAU.
!
!   \begin{verbatim}
!     AER(5,L=1:L1X) = Optical Depth in layer L (general visible OD)
!        This is not used in the calculation of J's but in calculating
!        the number in levels to insert in each layer L
!        Set for log-spacing of tau levels, increasing top-down.
!     AER(1:4,L) = aerosol+cloud OD (up to 4 types, index type = ADX(1:4,L)
!     AER(5,L) = Rayleigh-not used here
!   \end{verbatim}
!
!     N.B. the TTAU, etc caluclate here are not really used elsewhere.
!     \newline \newline
!
!   The log-spacing parameters have been tested for convergence and chosen
!   to be within $0.5\%$ for ranges OD=1-500, rflect=$0-100\%$, mu0=0.1-1.0
!   use of ATAU = 1.18 and min = 0.01, gives at most +135 pts for OD=100 
!
! !LOCAL VARIABLES:
      integer JTOTL,I,L,L2 
      real*8  DTAUX(L1X),TTAU(L2X+1),DTAUJ, ATAU1,ATAULN,ATAUM,ATAUN1
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
!BOC
!
!---Reinitialize arrays
      TTAU(:)  = 0.d0
      JXTRA(:) = 0
!
!---Set up total optical depth over each CTM level (L=1:L1X)
!---   DTAUX(L) = bulk properties (OD) of each CTM layer

      do L = 1,L1X
!  Total optical depth from all elements I=1:4 = clouds  + 3 aerosol types
!    Assume here that AER(1:4, 1:L1X) is 'visible' Optical Depth = 600 nm
!    do NOT count if ADX = 0
          DTAUX(L)   = 0.d0
        do I = 1,4
          if (ADX(I,L) .gt. 0) DTAUX(L) = DTAUX(L) + AER(I,L)
        enddo
      enddo
!
!---combine these edge- and mid-layer points into grid of size:
!---              L2X+1 = 2*L1X+1 = 2*L_+3
!---calculate column optical depths above each level, TTAU(1:L2X+1)
!---      note that TTAU(L2X+1)=0 and TTAU(1)=total OD
!
!---Divide thick layers to achieve better accuracy in the scattering code
!---In the original fast-J, equal sub-layers were chosen, this is wasteful
!---and this new code (ver 5.3) uses log-scale:  
!---        Each succesive layer (down) increase thickness by ATAU > 1
!---        e.g., if ATAU = 2, a layer with OD = 15 could be divided into
!---        4 sub-layers with ODs = 1 - 2 - 4 - 8
!---The key parameters are:
!---        ATAU = factor increase from one layer to the next
!---        ATAUMN = the smallest OD layer desired
!---        JTAUMX = maximum number of divisions (i.e., may not get to ATAUMN)
!---These are hardwired below, can be changed, but have been tested/optimized

      ATAU1  = ATAU - 1.d0
      ATAULN = log(ATAU)
        TTAU(L2X+1)  = 0.0d0
      do L2 = L2X,1,-1
        L         = (L2+1)/2
        DTAUJ     = 0.5d0 * DTAUX(L)
        TTAU(L2)  = TTAU(L2+1) + DTAUJ
!---Now compute the number of log-spaced sub-layers to be added in
!---   the interval TTAU(L2) > TTAU(L2+1)
!---The objective is to have successive TAU-layers increasing by factor ATAU >1
!---the number of sub-layers + 1
        if (TTAU(L2) .lt. ATAU0) then
          JXTRA(L2) = 0
        else
          ATAUM    = max(ATAU0, TTAU(L2+1))
          ATAUN1 = log(TTAU(L2)/ATAUM) / ATAULN
          JXTRA(L2) = min(JTAUMX, max(0, int(ATAUN1 - 0.5d0)))
        endif
      enddo

!---check on overflow of arrays, cut off JXTRA at lower L if too many levels
      JTOTL    = L2X + 2
      do L2 = L2X,1,-1
        JTOTL  = JTOTL + JXTRA(L2)
        if (JTOTL .gt. NX/2)  then
          write(6,'(A,2I5,F9.2)') 'N_/L2_/L2-cutoff JXTRA:',NX,L2X,L2
          do L = L2,1,-1
            JXTRA(L) = 0
          enddo
          go to 10
        endif
      enddo
  10  continue

      return
      end subroutine EXTRAL
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: OPMIE
!
! !INTERFACE:
!

      subroutine OPMIE & 3,11
     &   (KW,KM,WAVEL,ABX,AER,ADX,U0,RFLECT,AMF,JXTRA,FMEAN, FJTOP,FJBOT)
!
! !USES:
!
      use FastJX53cJvaluesVars_mod   , only : QAA, SSA, PAA, ATAU0
      use FastJX53cCTMparameters_mod , only : L1_, L2_, L_
      use FastJX53cMIEparameters_mod , only : M_, N_
      use FastJX53cCoreScattering_mod, only : MIESCT
!
      implicit none
!
!
! !INPUT PARAMETERS:
      real*8 , intent(in)  ::  WAVEL
               ! wavelength of bin (in nm) - not now used
      real*8 , intent(in)  ::  AER(5,L1_)
               ! 5 vertical profiles of Optical Depth in each layer
      real*8 , intent(in)  ::  ABX(L1_)
               ! vertical profiles of ABSORPTION Optical Depth in each layer
               ! includes O2 and O3 for now (BC under aerosols)
      real*8 , intent(in)  ::  AMF(L1_,L1_)
      real*8 , intent(in)  ::  U0
               ! cos (SZA)
      real*8 , intent(in)  ::  RFLECT
               ! Lambertian albedo of surface
      integer, intent(in)  ::  KW           
               ! wavelength bin # (1:18)
      integer, intent(in)  ::  KM           
               ! wavelength index for Mie properties (1:4 = 300-400-600-999 nm)
      integer, intent(in)  ::  ADX(5,L1_)
               ! integer index of the scattering properties of each AER
               ! 1:4 are reserved for aerosols and clouds
               ! 5 is meant only for Rayleigh scattering!
      integer, intent(in)  ::  JXTRA(L2_+1)
               ! number 0:J = no. of additional levels to be inserted
!
! !OUTPUT PARAMETERS:
      real*8 , intent(out) ::  FMEAN(L_)
               ! mean actinic flux at standard CTM levels (mid-layer)
      real*8 , intent(out) ::  FJTOP,FJBOT
! !DESCRIPTION:
! \begin{verbatim}
!
!     DTAUX    Local optical depth of each CTM level
!     TTAU     Optical depth of air vertically above each point (to top of atm)
!     FTAU     Attenuation of solar beam
!     POMEGA   Scattering phase function
!
!---new Ver 5.3 code adds sub-layers (# = JXTRA(L2)) using ATAU as the 
!   factor increase from sub-layer to sub-layer 

!  fast-J Mie code for J_s, only uses 8-term expansion, 4-Gauss pts
!  Currently allow up to A_ aerosol phase functions (at all altitudes) to
!  be associated with optical depth AER(1:L2_) = aerosol opt.depth @ 1000 nm
!  
!  Pick Mie-wavelength with phase function and Qext: e.g., 
!  01 RAYLE = Rayleigh phase
!  02 ISOTR = isotropic
!  03 ABSRB = fully absorbing 'soot', wavelength indep.
!  04 X_Bkg = backgrnd stratospheric sulfate (n=1.46,log-norm:r=.09um/sigma=.6)
!  05 X_Vol = volcanic stratospheric sulfate (n=1.46,log-norm:r=.08um/sigma=.8)
!. . .
!  11 W_C13 = water cloud (C1/Deirm.) (n=1.335, gamma:  r-mode=13.3um /alpha=6)
!. . .
!  13 Ice-H = hexagonal ice cloud (Mishchenko)
!  14 Ice-I = irregular ice cloud (Mishchenko)
!
!  Choice of the 4 aerosol/cloud indices ADX is made earlier
!  Optical depths for the 4 (aerosol+clouds) = AER
!  \end{verbatim}
!
! !LOCAL VARIABLES:
      integer JNDLEV(L_),JADDLV(L2_+1),JADDTO(L2_+1),L2LEV(L2_+1) &
     &       ,JTOTL,I,II,J,K,L,IX,JK,   L2,L2L,L22,LZ,LZZ,NDZ
!
      real*8  QXMIE(5),XLAER(5),SSALB(5),DTAUX(L1_),PIAER(5,L1_) &
     &       ,POMEGAJ(2*M_,L2_+1),TTAU(L2_+1),FTAU(L1_) &
     &       ,FTAU2(L2_+1),DTTAU,DFTAU,dPOMEGA(2*M_) &
     &       ,XLO2,XLO3,XLRAY,XLTAU,ZK,TAUDN,TAUUP,ZK2 &
     &       ,DTAUJ,DTAUAD,TAUBTM,TAUTOP,FBTM,FTOP,POMEGAB(2*M_) &
     &       ,ATAUA,ATAUZ
!--- variables used in mie code-----------------------------------------
      real*8   FJ(N_),POMEGA(2*M_,N_),FZ(N_),ZTAU(N_),ZREFL,ZU0,ZFLUX
      real*8   FJT,FJB
      integer  MFIT, ND
!
! !AUTHOR:
!  Michael Prather
!
! !REVISION HISTORY:
!  Initial code.
!
!EOP
!-------------------------------------------------------------------------
!BOC
!---Reinitialize arrays
      ZTAU(:)     = 0.d0
      FZ(:)       = 0.d0
      POMEGA(:,:) = 0.d0


!---Set up optical depth DTAUX(L), and scattering fraction PIAER(1:5,L)
!---    where L = 1:L1_ = bulk properties of each CTM layer.
      do L = 1,L1_

        do I = 1,4
          if (ADX(I,L) .eq. 0)  then
            QXMIE(I) = 0.d0
            SSALB(I) = 0.d0
          else
!---for Mie code scale extinction at 600 nm to wavelength WAVEL (QXMIE)
            QXMIE(I) = QAA(KM,ADX(I,L))/QAA(3,ADX(I,L))
            SSALB(I) = SSA(KM,ADX(I,L))
          endif
        enddo
!---special case for Rayleigh scattering
            QXMIE(5) = 1.d0
            SSALB(5) = 1.d0
        do I = 1,5
          XLAER(I) = AER(I,L)*QXMIE(I)
        enddo

          DTAUX(L) = ABX(L)
        do I = 1,5
          DTAUX(L) = DTAUX(L) + XLAER(I)
        enddo
!---fractional extinction for Rayleigh scattering and each aerosol type
        do I = 1,5
          PIAER(I,L) = SSALB(I)*XLAER(I)/DTAUX(L)
        enddo

      enddo

!---Calculate attenuated incident beam exp(-TTAU/U0 = DTAUX * AirMassFactor)
!---      at the edges of the CTM layers L=1:L1_
      do L = 1,L1_
        if (AMF(L,L) .gt. 0.0d0) then
            XLTAU = 0.0d0
          do I = 1,L1_
            XLTAU = XLTAU + DTAUX(I)*AMF(I,L)
          enddo
          if (XLTAU .gt. 76.d0) then   ! zero out flux at 1e-33
            FTAU(L) = 0.d0
          else
            FTAU(L) = exp(-XLTAU)
          endif
        else
          FTAU(L)   = 0.0d0
        endif
      enddo
!
!---Define the total scattering phase fn for each CTM layer L=1:L_+1
!---   from a DTAUX-wt_d mix of aerosols, cloud & Rayleigh
!---No. of quadrature pts fixed at 4(M_), expansion of phase fn @ 8
      MFIT = 2*M_
      do L = 1,L1_
        do I = 1,MFIT
           POMEGAJ(I,L) = 0.d0
          do K = 1,5
           POMEGAJ(I,L)=POMEGAJ(I,L) + PIAER(K,L)*PAA(I,KM,ADX(K,L))
          enddo
        enddo
      enddo

!--printout diagnositcs of different aerosol+cld contrib to OD
!      if(KW.eq.18) then
!      do L=1,L1_
!      write(6,'(3i5,1p,20e12.5)') L,JXTRA(L+L),JXTRA(L+L-1),
!     &   DTAUX(L),(AER(I,L),I=1,5)
!      enddo
!      endif

!
!------------------------------------------------------------------------
!  Take optical properties on CTM layers and convert to a photolysis
!  level grid corresponding to layer centres and boundaries. This is
!  required so that J-values can be calculated for the centre of CTM
!  layers; the index of these layers is kept in the JNDLEV array.
!------------------------------------------------------------------------
!
!---Now combine the CTM layer edges (1:L_+2) with the CTM mid-layer
!---    points (1:L_) plus 1 for the mid point of added top layer.

!---combine these edge- and mid-layer points into grid of size:
!---              L2_+1 = 2*L1_+1 = 2*L_+3
!---calculate column optical depths above each level, TTAU(1:L2_+1)
!---      note that TTAU(L2_+1)=0 and TTAU(1)=total OD
        TTAU(L2_+1) = 0.0d0
      do L2 = L2_,1,-1
        L          = (L2+1)/2
        DTAUJ      = 0.5d0 * DTAUX(L)
        TTAU(L2)   = TTAU(L2+1) + DTAUJ
      enddo
!
!---reflected flux from surface
      if (U0 .gt. 0.d0) then
        ZFLUX = U0*FTAU(1)*RFLECT/(1.d0+RFLECT)
      else
        ZFLUX = 0.d0
      endif
!
!---calculate attenuated beam FTAU2 on the new doubled-levels L2=1:L2_+1
!---       calculate FTAU2 at CTM mid-layers from sqrt
!---       L2_ = 2*L1_ = 2*L_+2

        FTAU2(L2_+1) = 1.0d0
        FTAU2(L2_)   = sqrt(1.0d0*FTAU(L1_))
        FTAU2(L2_-1) = FTAU(L1_)
      do L2 = L2_-3,1,-2
        L           = (L2+1)/2
        FTAU2(L2)   = FTAU(L)
        FTAU2(L2+1) = sqrt(FTAU(L+1)*FTAU(L))
      enddo
!
!  Calculate scattering properties, level centres then level boundaries
! ***be careful of order, we are shifting the 'POMEGAJ' upward in index***
      do L2 = L2_,2,-2
        L   = L2/2
        do I = 1,MFIT
          POMEGAJ(I,L2) = POMEGAJ(I,L)
        enddo
      enddo
!---lower boundary value is set (POMEGAJ(I,1), but set upper:
        do I = 1,MFIT
          POMEGAJ(I,L2_+1) = POMEGAJ(I,L2_)
        enddo
!---now have POMEGAJ filled at even points from L2=3:L2_-1
!---use inverse interpolation for correct tau-weighted values at edges
      do L2 = 3,L2_-1,2
        TAUDN = TTAU(L2-1)-TTAU(L2)
        TAUUP = TTAU(L2)-TTAU(L2+1)
        do I = 1,MFIT
          POMEGAJ(I,L2) = (POMEGAJ(I,L2-1)*TAUDN +  &
     &             POMEGAJ(I,L2+1)*TAUUP) / (TAUDN+TAUUP)
        enddo
      enddo
!---at this point FTAU2(1:L2_+1) and POMEAGJ(1:8, 1:L2_+1)
!---    where FTAU2(L2_+1) = 1.0 = top-of-atmos, FTAU2(1) = surface
!
!------------------------------------------------------------------------
!  Calculate cumulative total and define levels we want J-values at.
!  Sum upwards for levels, and then downwards for Mie code readjustments.
!
!     JXTRA(L2)  Number of new levels to add between (L2) and (L2+1)
!           ***JXTRA(1:L2_+1) is calculated based on the aerosol+cloud OD_s
!     JADDLV(L2)  Number of new levels actually added at each wavelength
!            where JADDLV = 0 when there is effectively no FTAU2 
!     JADDTO(L2)   Total number of new levels to add to and above level (L2)
!     JNDLEV(L) = L2 index that maps on CTM mid-layer L
!
!------------------------------------------------------------------------

!---JADDLV(L2=1:L2_) = number of levels to add between TTAU2(L2) and TTAU(L2+1)
!---    JADDLV is taken from JXTRA, which is based on visible OD.
!---    JADDTO(L2=1:L2_+1) is the cumulative number of levels to be added
!---note that JADDLV and JADDTO will change with wavelength and solar zenith

!--now try to insert additional levels for thick clouds, ONLY IF FTAU2 > 1.e-8
!-- this will cut off additional levels where the solar beam is negligible.

      do L2 = 1,L2_
        if (FTAU2(L2+1) .lt. 1.d-30) then
          JADDLV(L2) = 0
        else
          JADDLV(L2) = JXTRA(L2)
        endif
      enddo
        JADDTO(L2_+1) = 0
      do L2 = L2_,1,-1
        JADDTO(L2) = JADDTO(L2+1) + JADDLV(L2)
      enddo

!---expanded grid now included CTM edge and mid layers plus expanded 
!---    grid to allow for finer delta-tau at tops of clouds.
!---    DIM of new grid = L2_ + JADDTO(1) + 1

!---L2LEV(L2) = L2-index for old level L2 in expanded J-grid (w/JADDLV)
!     in absence of JADDLV, L2LEV(L2) = L2
        L2LEV(1)  = 1
      do L2 = 2,L2_+1
        L2LEV(L2) = L2LEV(L2-1) + 1 + JADDLV(L2-1)
      enddo

!---JNDLEV(L=1:L_) = L2-index in expanded grid for CTM mid-layer L 
      do L = 1,L_
        JNDLEV(L) = L2LEV(2*L)
      enddo

!---------------------SET UP FOR MIE CODE-------------------------------
!
!  Transpose the ascending TTAU grid to a descending ZTAU grid.
!  Double the resolution - TTAU points become the odd points on the
!  ZTAU grid, even points needed for asymm phase fn soln, contain 'h'.
!  Odd point added at top of grid for unattenuated beam   (Z='inf')
!
!  The following mapping holds for JADDLV=0
!        Surface:   TTAU(1)    ==> ZTAU(2*L2_+1)
!        Top:       TTAU(L2_)  ==> ZTAU(3)
!        Infinity:     0.0     ==> ZTAU(1)
!        index: 2*(L2_+1-L2)+1 ==> LZ
!
!  Mie scattering code only used from surface to level L2_
!------------------------------------------------------------------------
!
!------------------------------------------------------------------------
!  Insert new levels, working downwards from the top of the atmosphere
!  to the surface (down in 'LZ', up in 'L2'). This allows ztau and pomega
!  to be incremented linearly (in a +ve sense), and the flux fz to be
!  attenuated top-down (avoiding problems where lower level fluxes are
!  zero).
!
!    zk        fractional increment in level
!    dTTAU     change in ttau per increment    (linear, positive)
!    dPOMEGA   change in pomega per increment  (linear)
!    ftaulog   change in ftau per increment    (exponential, normally < 1)
!
!------------------------------------------------------------------------
!
!  Ascend through atmosphere transposing grid and adding extra points
!  remember L2=1 is surface of CTM, but last layer (LZ) in scattering code.
!  there are twice the number of layers in the LZ arrays (2*L2_ + 2*JADDTO + 1)
!    because we need to insert the intermediate layers (even LZ) for the 
!    asymmetric scattering code.


!  Transfer the L2=1:L2_+1 values (TTAU,FTAU2,POMEGAJ) onto the reverse
!    order, expanded, doubled-level scatter grid. 
!    Note that we need to deal with the expansion by JADD levels (L2L).
!      These JADDLV levels are skipped and need to be interpolated later.
!    Note that only odd LZ levels are filled, 

      NDZ = 2*L2_ + 2*JADDTO(1) + 1

!   Note that the successive sub-layers have the ratio in OD of ATAU
!      ATAUA = (ATAU - 1.d0)/ATAU     ! this is the limit for L22=>inf

      do L2 = 1,L2_+1          ! L2 = index of CTM edge- and mid-layers
        L2L = L2LEV(L2)        ! L2L = index for L2 in expanded scale(JADD)
        LZ  = NDZ + 2 - 2*L2L  ! LZ = index for L2 in scatt arrays
          ZTAU(LZ) = TTAU(L2)
          FZ(LZ)   = FTAU2(L2)
        do I=1,MFIT
          POMEGA(I,LZ) = POMEGAJ(I,L2)
        enddo
      enddo

!   Now go thru the pairs of L2 levels to see if we need JADD levels
      do L2 = 1,L2_             ! L2 = index of CTM edge- and mid-layers
        L2L = L2LEV(L2)         ! L2L = index for L2 in expanded scale(JADD)
        LZ  = NDZ + 2 - 2*L2L   ! LZ = index for L2 in scatt arrays
        L22 = L2LEV(L2+1) - L2LEV(L2) - 1   ! L22 = 0 if no added levels
       if (L22 .gt. 0) then
          TAUBTM = TTAU(L2)
          TAUTOP = TTAU(L2+1)
          FBTM   = FTAU2(L2)
          FTOP   = FTAU2(L2+1)
         do I = 1,MFIT
          POMEGAB(I) = POMEGAJ(I,L2)
         enddo

!---to fit L22 new layers between TAUBOT > TAUTOP, calculate new 1/ATAU factor
!---  such that TAU(just above TAU-btm) = ATUAZ * TAUBTM < TAUBTM

          ATAUZ = exp(-log(TAUBTM/max(TAUTOP,ATAU0))/float(L22+1))

        do L = 1,L22           ! add odd levels between L2LEV(L2) & L2LEV(L2+1)
          LZZ = LZ - 2*L       ! LZZ = index(odd) of added level in scatt arrays
          ZTAU(LZZ) = TAUBTM * ATAUZ
          ATAUA=(TAUBTM-ZTAU(LZZ))/(TAUBTM-TAUTOP) !fraction from TAUBTM=>TAUTOP
          if (FBTM .lt. 1.d-32) then
            FZ(LZZ) = 0.d0
          else    
            FZ(LZZ) = FBTM * (FTOP/FBTM)**ATAUA
          endif
          do I = 1,MFIT
            POMEGA(I,LZZ) = POMEGAB(I) +  &
     &               ATAUA*(POMEGAJ(I,L2+1)-POMEGAB(I))
          enddo
            TAUBTM       = ZTAU(LZZ)
            FBTM         = FZ(LZZ)
          do I = 1,MFIT
            POMEGAB(I) = POMEGA(I,LZZ)
          enddo
        enddo
       endif
      enddo

!   Now fill in the even points with simple interpolation in scatter arrays:
      do LZ = 2,NDZ-1,2
        ZTAU(LZ) = 0.5d0*(ZTAU(LZ-1)+ZTAU(LZ+1))
        FZ(LZ)   = sqrt(FZ(LZ-1)*FZ(LZ+1))
       do I=1,MFIT
        POMEGA(I,LZ) = 0.5d0*(POMEGA(I,LZ-1)+POMEGA(I,LZ+1))
       enddo
      enddo
      
      ND = NDZ
      ZU0 = U0
      ZREFL = RFLECT

!---PRINT diagnostics
!      write(6,'(A,2I6)') 'Total levels of photolysis in OPMIE',ND
      if(ND .gt. N_) then
        write(6,'(a,2i9)') ' overflow of scatter arrays:',ND,N_
        stop
      endif

!-----------------------------------------------------------------------
      call MIESCT(FJ,FJT,FJB,POMEGA,FZ,ZTAU,ZFLUX,ZREFL,ZU0,MFIT,ND)
!-----------------------------------------------------------------------

!---Move mean intensity from scatter array FJ(LZ=1:ND) 
!---              to CTM mid-level array FMEAN(L=1:L_)
      do L = 1,L_
        L2L = JNDLEV(L)
        LZ  = ND+2 - 2*L2L
        FMEAN(L) = FJ(LZ)
      enddo

!---fluxes reflected at top, incident at bottom (1/2 layer flux)
        FJTOP = FJT
        FJBOT = FJB

      return
      end subroutine OPMIE
!EOC
!-------------------------------------------------------------------------

      end module FastJX53cCoreFastj_mod