LCOV - code coverage report
Current view: top level - chemistry/mozart - mo_jshort.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 477 0.0 %
Date: 2025-01-13 21:54:50 Functions: 0 16 0.0 %

          Line data    Source code
       1             : #ifdef AIX
       2             : #define USE_ESSL
       3             : #endif
       4             : #define USE_BDE
       5             : 
       6             :       module mo_jshort
       7             : 
       8             :       use shr_kind_mod,      only : r8 => shr_kind_r8
       9             :       use physconst,         only : pi
      10             :       use mo_constants,      only : d2r
      11             :       use cam_abortutils,    only : endrun
      12             :       use cam_logfile,       only : iulog
      13             :       use spmd_utils,        only : masterproc
      14             :       use ppgrid,            only : pver
      15             :       use phys_control,      only : waccmx_is
      16             : 
      17             :       implicit none
      18             : 
      19             :       interface jshort
      20             :          module procedure jshort_photo
      21             :          module procedure jshort_hrates
      22             :       end interface
      23             : 
      24             :       private
      25             :       public :: jshort_init
      26             :       public :: jshort_timestep_init
      27             :       public :: jshort
      28             :       public :: sphers
      29             :       public :: slant_col
      30             :       public :: nj
      31             : 
      32             :       save
      33             : 
      34             : !------------------------------------------------------------------------------
      35             : !     ... define altitude and wavelength parameters
      36             : !------------------------------------------------------------------------------
      37             :       integer, parameter  :: num_ms93tuv = 4       ! wavelength bins for MS, 93
      38             :       integer, parameter  :: nw_ms93     = 4       ! wavelength bins for MS, 93
      39             :       integer, parameter  :: nsrc_tot    = 19      ! total bins for SRC
      40             :       integer, parameter  :: nsrb_tot    = 14      ! total bins <200nm for SRB
      41             :       integer, parameter  :: nsrbtuv     = 17      ! total SRB bins in TUV
      42             :       real(r8), parameter :: hc          = 6.62608e-34_r8 * 2.9979e8_r8 / 1.e-9_r8
      43             :       real(r8), parameter :: wc_o2_a     = 175.05_r8   ! (nm)
      44             :       real(r8), parameter :: wc_o2_b     = 242.37_r8   ! (nm)
      45             :       real(r8), parameter :: wc_o3_a     = 310.32_r8   ! (nm)
      46             :       real(r8), parameter :: wc_o3_b     = 1179.87_r8  ! (nm)
      47             :       real(r8), parameter :: we_ms(nw_ms93+1) = (/ 181.6_r8, 183.1_r8, 184.6_r8, 190.2_r8, 192.5_r8 /)
      48             : 
      49             :       integer  :: nw                                 ! Number of wavelength bins <200nm
      50             :       integer  :: nj                                 ! Number of photorates
      51             :       real(r8) :: wtno50(6,2)
      52             :       real(r8) :: wtno90(6,2)
      53             :       real(r8) :: wtno100(6,2)
      54             :       real(r8) :: csno50(6,2)
      55             :       real(r8) :: csno90(6,2)
      56             :       real(r8) :: csno100(6,2)
      57             :       real(r8) :: ac(20,nsrbtuv)
      58             :       real(r8) :: bc(20,nsrbtuv)     ! chebyshev polynomial coeffs
      59             :       real(r8) :: wave_num(nsrbtuv)
      60             :       real(r8), allocatable :: wc(:)
      61             :       real(r8), allocatable :: we(:)
      62             :       real(r8), allocatable :: wlintv(:)
      63             :       real(r8), allocatable :: bde_o2_a(:)
      64             :       real(r8), allocatable :: bde_o2_b(:)
      65             :       real(r8), allocatable :: bde_o3_a(:)
      66             :       real(r8), allocatable :: bde_o3_b(:)
      67             :       real(r8), allocatable :: etfphot(:)
      68             :       real(r8), allocatable :: etfphot_ms93(:)
      69             :       real(r8), allocatable :: xs_o2src(:)
      70             :       real(r8), allocatable :: xs_o3a(:)
      71             :       real(r8), allocatable :: xs_o3b(:)
      72             :       real(r8), allocatable :: xs_wl(:,:)
      73             : 
      74             :       real(r8), parameter :: lno2_llimit = 38._r8 ! ln(NO2) lower limit
      75             :       real(r8), parameter :: lno2_ulimit = 56._r8 ! ln(NO2) upper limit
      76             : 
      77             :       contains
      78             : 
      79           0 :       subroutine jshort_init( xs_coef_file, xs_short_file, sht_indexer )
      80             : !------------------------------------------------------------------------------
      81             : !    ... initialize photorates for 120nm <= lambda <= 200nm
      82             : !------------------------------------------------------------------------------
      83             : 
      84             :       use mo_util,        only : rebin
      85             :       use solar_irrad_data,  only : data_nbins=>nbins, data_we => we, data_etf => sol_etf
      86             : 
      87             :       implicit none
      88             : 
      89             : !------------------------------------------------------------------------------
      90             : !    ... dummy arguments
      91             : !------------------------------------------------------------------------------
      92             :       character(len=*), intent(in) :: xs_coef_file, xs_short_file
      93             :       integer, intent(inout)       :: sht_indexer(:)
      94             : 
      95             : !------------------------------------------------------------------------------
      96             : !     ... set the wavelength grid, exoatmospheric flux,
      97             : !         and cross sections (for <200nm) - contained in
      98             : !         a NetCDF file
      99             : !------------------------------------------------------------------------------
     100           0 :       call get_crs( xs_short_file, sht_indexer )
     101           0 :       if(masterproc) then
     102           0 :          write(iulog,*) ' '
     103           0 :          write(iulog,*) '============================================'
     104           0 :          write(iulog,*) 'jshort_init: finished get_crs'
     105           0 :          write(iulog,*) 'jshort_init: nj, nw = ',nj,nw
     106           0 :          write(iulog,*) 'jshort_init: wc'
     107           0 :          write(iulog,*) wc(:)
     108           0 :          write(iulog,*) '============================================'
     109           0 :          write(iulog,*) ' '
     110             :       end if
     111           0 :       we(:nw)  = wc(:nw) - .5_r8*wlintv(:nw)
     112           0 :       we(nw+1) = wc(nw) + .5_r8*wlintv(nw)
     113           0 :       if(masterproc) then
     114           0 :          write(iulog,*) ' '
     115           0 :          write(iulog,*) '-------------------------------------------'
     116           0 :          write(iulog,*) 'jshort_init: diagnostics before rebin'
     117           0 :          write(iulog,*) 'jshort_init: data_nbins, nw = ',data_nbins,nw
     118           0 :          write(iulog,*) 'jshort_init: data_we range'
     119           0 :          write(iulog,'(1p,5g15.7)') minval(data_we(:)),maxval(data_we(:))
     120           0 :          write(iulog,*) 'jshort_init: we range'
     121           0 :          write(iulog,'(1p,5g15.7)') minval(we(:)),maxval(we(:))
     122             :       end if
     123           0 :       call rebin( data_nbins, nw, data_we, we, data_etf, etfphot )
     124           0 :       if(masterproc) then
     125           0 :          write(iulog,*) 'jshort_init: etfphot'
     126           0 :          write(iulog,'(1p,5g15.7)') etfphot(:)
     127           0 :          write(iulog,*) '-------------------------------------------'
     128           0 :          write(iulog,*) ' '
     129           0 :          write(iulog,*) 'jshort_init: diagnostics for ms93'
     130           0 :          call rebin( data_nbins, nw_ms93, data_we, we_ms, data_etf, etfphot_ms93 )
     131           0 :          write(iulog,'(1p,5g15.7)') etfphot_ms93(:)
     132           0 :          write(iulog,*) '-------------------------------------------'
     133           0 :          write(iulog,*) ' '
     134             :       end if
     135             : !------------------------------------------------------------------------------
     136             : !     ... loads Chebyshev polynomial Coeff
     137             : !------------------------------------------------------------------------------
     138           0 :       call xs_init(xs_coef_file)
     139             : 
     140             : !------------------------------------------------------------------------------
     141             : !     ... initialize no photolysis
     142             : !------------------------------------------------------------------------------
     143           0 :       call jno_init
     144             : 
     145           0 :       end subroutine jshort_init
     146             : 
     147           0 :       subroutine get_crs( xs_short_file, sht_indexer )
     148             : !=============================================================================
     149             : !   PURPOSE:
     150             : !   Reads a NetCDF file that contains:
     151             : !     Cross_sections*quantum yield data for species <200nm.
     152             : !     Exoatmospheric flux on the wavelength grid of the crs
     153             : !=============================================================================
     154             : !   PARAMETERS:
     155             : !     Input:
     156             : !      xs_short_file.... NetCDF file that contains the crs*QY for wavenum species
     157             : !
     158             : !     Output:
     159             : !      xs_species.. Cross Sections * QY data for each species
     160             : !      etfphot..... Exoatmospheric flux in photons cm-2 s-1 nm-1
     161             : !      etfphot_ms93.Minshwanner and Siskind JNO SRB etf (on MS93 grid)
     162             : !      wc.......... wavelength center (nm)
     163             : !      numwl ...... Number of wavelengths < 200nm in NetCDF input file
     164             : !      wlintv ..... Wavelength inteval for grid, nm
     165             : !=============================================================================
     166             : !   EDIT HISTORY:
     167             : !   Created by Doug Kinnison, 1/14/2002
     168             : !   Modified by S. Walters, 4/2/2003
     169             : !=============================================================================
     170             : 
     171           0 :       use chem_mods,      only : phtcnt, pht_alias_lst, rxt_tag_lst
     172             :       use ioFileMod,      only : getfil
     173             :       use error_messages, only : alloc_err
     174             :       use pio,            only : file_desc_t, pio_get_var, pio_closefile, pio_noerr, &
     175             :            pio_seterrorhandling, pio_bcast_error, pio_internal_error, pio_inq_varid, &
     176             :            pio_inq_dimlen, pio_nowrite, pio_inq_dimid
     177             :       use cam_pio_utils,  only : cam_pio_openfile
     178             :       implicit none
     179             : 
     180             : !------------------------------------------------------------------------------
     181             : !       ... dummy arguments
     182             : !------------------------------------------------------------------------------
     183             :       integer, intent(inout)       :: sht_indexer(:)
     184             :       character(len=*), intent(in) :: xs_short_file
     185             : 
     186             : !------------------------------------------------------------------------------
     187             : !       ... local variables
     188             : !------------------------------------------------------------------------------
     189             :       integer :: wn
     190             :       type(file_desc_t) :: ncid
     191             :       integer :: ierr
     192             :       integer :: i, m, ndx
     193             :       integer :: varid, dimid
     194             :       integer :: wrk_ndx(phtcnt)
     195           0 :       real(r8), allocatable :: xs_species(:)
     196             :       character(len=256) :: locfn
     197             : 
     198             : !------------------------------------------------------------------------------
     199             : !       ... open NetCDF File
     200             : !------------------------------------------------------------------------------
     201           0 :       call getfil(xs_short_file, locfn, 0)
     202           0 :       call cam_pio_openfile(ncid, trim(locfn), PIO_NOWRITE)
     203             : 
     204             : !------------------------------------------------------------------------------
     205             : !       ... get dimensions
     206             : !------------------------------------------------------------------------------
     207           0 :       ierr = pio_inq_dimid( ncid, 'numwl', dimid )
     208           0 :       ierr = pio_inq_dimlen( ncid, dimid, nw )
     209             : 
     210             : !------------------------------------------------------------------------------
     211             : !       ... check for cross section in dataset
     212             : !------------------------------------------------------------------------------
     213           0 :       call pio_seterrorhandling(ncid, pio_bcast_error)
     214             :       do m = 1,phtcnt
     215             :          if( pht_alias_lst(m,1) == ' ' ) then
     216             :             ierr = pio_inq_varid( ncid, rxt_tag_lst(m), varid )
     217             :             if( ierr == PIO_noerr ) then
     218             :                sht_indexer(m) = varid
     219             :             end if
     220             :          else if( pht_alias_lst(m,1) == 'userdefined' ) then
     221             :             sht_indexer(m) = -1
     222             :          else
     223             :             ierr = pio_inq_varid( ncid, pht_alias_lst(m,1), varid )
     224             :             if( ierr == PIO_noerr ) then
     225             :                sht_indexer(m) = varid
     226             :             else
     227             :                write(iulog,*) 'get_crs : ',rxt_tag_lst(m)(:len_trim(rxt_tag_lst(m))),' alias ', &
     228             :                     pht_alias_lst(m,1)(:len_trim(pht_alias_lst(m,1))),' not in dataset'
     229             :                call endrun
     230             :             end if
     231             :          end if
     232             :       end do
     233           0 :       call pio_seterrorhandling(ncid, pio_internal_error)
     234             : 
     235           0 :       if (masterproc) then
     236           0 :          write(iulog,*) ' '
     237           0 :          write(iulog,*) '###############################################'
     238           0 :          write(iulog,*) 'get_crs: sht_indexer'
     239           0 :          write(iulog,'(10i6)') sht_indexer(:)
     240           0 :          write(iulog,*) '###############################################'
     241           0 :          write(iulog,*) ' '
     242             :       endif
     243             : 
     244           0 :       nj = 0
     245             :       do m = 1,phtcnt
     246             :          if( sht_indexer(m) > 0 ) then
     247             :             if( any( sht_indexer(:m-1) == sht_indexer(m) ) ) then
     248             :                cycle
     249             :             end if
     250             :             nj = nj + 1
     251             :          end if
     252             :       end do
     253             : 
     254             : !------------------------------------------------------------------------------
     255             : !       ... allocate arrays
     256             : !------------------------------------------------------------------------------
     257           0 :       allocate( wc(nw),stat=ierr )
     258           0 :       if( ierr /= 0 ) then
     259           0 :          call alloc_err( ierr, 'get_crs', 'wc', nw )
     260             :       end if
     261           0 :       allocate( we(nw+1),stat=ierr )
     262           0 :       if( ierr /= 0 ) then
     263           0 :          call alloc_err( ierr, 'get_crs', 'we', nw+1 )
     264             :       end if
     265           0 :       allocate( wlintv(nw),stat=ierr )
     266           0 :       if( ierr /= 0 ) then
     267           0 :          call alloc_err( ierr, 'get_crs', 'wlintv', nw )
     268             :       end if
     269           0 :       allocate( etfphot(nw),stat=ierr )
     270           0 :       if( ierr /= 0 ) then
     271           0 :          call alloc_err( ierr, 'get_crs', 'etfphot', nw )
     272             :       end if
     273           0 :       allocate( bde_o2_a(nw),bde_o2_b(nw),bde_o3_a(nw),bde_o3_b(nw),stat=ierr )
     274           0 :       if( ierr /= 0 ) then
     275           0 :          call alloc_err( ierr, 'get_crs', 'bde_o2_a ... bde_o3_b', nw )
     276             :       end if
     277           0 :       allocate( etfphot_ms93(nw_ms93),stat=ierr )
     278           0 :       if( ierr /= 0 ) then
     279           0 :          call alloc_err( ierr, 'get_crs', 'etfphot_ms93', nw_ms93 )
     280             :       end if
     281           0 :       allocate( xs_o2src(nw),stat=ierr )
     282           0 :       if( ierr /= 0 ) then
     283           0 :          call alloc_err( ierr, 'get_crs', 'xs_o2src', nw )
     284             :       end if
     285           0 :       allocate( xs_o3a(nw),xs_o3b(nw),stat=ierr )
     286           0 :       if( ierr /= 0 ) then
     287           0 :          call alloc_err( ierr, 'get_crs', 'xs_o3a,xs_o3b', nw )
     288             :       end if
     289           0 :       allocate( xs_species(nw),xs_wl(nw,nj),stat=ierr )
     290           0 :       if( ierr /= 0 ) then
     291           0 :          call alloc_err( ierr, 'get_crs', 'xs_species,xs_wl', nw*nj )
     292             :       end if
     293             : 
     294             : !------------------------------------------------------------------------------
     295             : !       ... read arrays
     296             : !------------------------------------------------------------------------------
     297           0 :       ierr = pio_inq_varid( ncid, 'wc', varid )
     298           0 :       ierr = pio_get_var( ncid, varid, wc )
     299           0 :       ierr = pio_inq_varid( ncid, 'wlintv', varid )
     300           0 :       ierr = pio_get_var( ncid, varid, wlintv )
     301           0 :       ierr = pio_inq_varid( ncid, 'xs_o2src', varid )
     302           0 :       ierr = pio_get_var( ncid, varid, xs_o2src )
     303             :       ndx = 0
     304             :       do m = 1,phtcnt
     305             :          if( sht_indexer(m) > 0 ) then
     306             :             if( any( sht_indexer(:m-1) == sht_indexer(m) ) ) then
     307             :                cycle
     308             :             end if
     309             :             ierr = pio_get_var( ncid, sht_indexer(m), xs_species )
     310             :             ndx = ndx + 1
     311             :             xs_wl(:,ndx) = xs_species(:)*wlintv(:)
     312             :          end if
     313             :       end do
     314           0 :       deallocate( xs_species )
     315           0 :       if( ndx /= nj ) then
     316           0 :          write(iulog,*) 'get_crs : ndx count /= cross section count'
     317           0 :          call endrun
     318             :       end if
     319             :       !------------------------------------------------------------------------------
     320             :       !       ... get jo3 cross sections
     321             :       !------------------------------------------------------------------------------
     322           0 :       ierr = pio_inq_varid( ncid, 'jo3_a', varid )
     323           0 :       ierr = pio_get_var( ncid, varid, xs_o3a )
     324           0 :       ierr = pio_inq_varid( ncid, 'jo3_b', varid )
     325           0 :       ierr = pio_get_var( ncid, varid, xs_o3b )
     326             :       !------------------------------------------------------------------------------
     327             :       !       ... setup final sht_indexer
     328             :       !------------------------------------------------------------------------------
     329           0 :       ndx = 0
     330           0 :       wrk_ndx(:) = sht_indexer(:)
     331             :       do m = 1,phtcnt
     332             :          if( wrk_ndx(m) > 0 ) then
     333             :             ndx = ndx + 1
     334             :             i = wrk_ndx(m)
     335             :             where( wrk_ndx(:) == i )
     336             :                sht_indexer(:) = ndx
     337             :                wrk_ndx(:)     = -100000
     338             :             end where
     339             :          end if
     340             :       end do
     341             : 
     342           0 :       call pio_closefile( ncid )
     343             : 
     344             : #ifdef USE_BDE
     345           0 :       if (masterproc) write(iulog,*) 'Jshort using bdes'
     346             : #else
     347             :       if (masterproc) write(iulog,*) 'Jshort not using bdes'
     348             : #endif
     349           0 :       do wn = 1,nw
     350             : #ifdef USE_BDE
     351           0 :          bde_o2_a(wn) = max(0._r8, hc*(wc_o2_a - wc(wn))/(wc_o2_a*wc(wn)) )
     352           0 :          bde_o2_b(wn) = max(0._r8, hc*(wc_o2_b - wc(wn))/(wc_o2_b*wc(wn)) )
     353           0 :          bde_o3_a(wn) = max(0._r8, hc*(wc_o3_a - wc(wn))/(wc_o3_a*wc(wn)) )
     354           0 :          bde_o3_b(wn) = max(0._r8, hc*(wc_o3_b - wc(wn))/(wc_o3_b*wc(wn)) )
     355             : #else
     356             :          bde_o2_a(wn) = hc/wc(wn)
     357             :          bde_o2_b(wn) = hc/wc(wn)
     358             :          bde_o3_a(wn) = hc/wc(wn)
     359             :          bde_o3_b(wn) = hc/wc(wn)
     360             : #endif
     361             :       end do
     362             : 
     363           0 :       end subroutine get_crs
     364             : 
     365           0 :       subroutine xs_init(xs_coef_file)
     366             : !-------------------------------------------------------------
     367             : !       ... Loads XS_COEFFS containing the Chebyshev
     368             : !           polynomial coeffs necessary to calculate O2 effective
     369             : !           cross-sections
     370             : !-------------------------------------------------------------
     371             : 
     372           0 :       use ioFileMod,     only : getfil
     373             :       use units,         only : getunit, freeunit
     374             : 
     375             : !------------------------------------------------------------------------------
     376             : !    ... Dummy arguments
     377             : !------------------------------------------------------------------------------
     378             :       character(len=*), intent(in) :: xs_coef_file
     379             : 
     380             : !-------------------------------------------------------------
     381             : !     ... Local variables
     382             : !-------------------------------------------------------------
     383             :       integer :: unit   ! file unit number
     384             :       integer :: istat  ! i/o status
     385             :       integer :: i, j
     386             :       character(len=256) :: locfn
     387             : 
     388             : !----------------------------------------------------------------------
     389             : !       ... Get first strato photo rate file
     390             : !----------------------------------------------------------------------
     391           0 :          call getfil(xs_coef_file, locfn, 0)
     392             : !----------------------------------------------------------------------
     393             : !       ... open file
     394             : !----------------------------------------------------------------------
     395           0 :          unit = getunit()
     396             :          open( unit   = unit, &
     397             :                file   = trim(locfn), &
     398             :                status = 'old', &
     399             :                form   = 'formatted', &
     400           0 :                iostat = istat )
     401           0 :          if( istat /= 0 ) then
     402             : !----------------------------------------------------------------------
     403             : !       ... Open error exit
     404             : !----------------------------------------------------------------------
     405           0 :             write(iulog,*) 'xs_init: error ',istat,' opening file ',trim(locfn)
     406           0 :             call endrun
     407             :          end if
     408             : !----------------------------------------------------------------------
     409             : !       ... read file
     410             : !----------------------------------------------------------------------
     411           0 :          read(unit,901)
     412           0 :          do i = 1,20
     413           0 :             read(unit,903,iostat=istat) ac(i,:)
     414           0 :             if( istat /= 0 ) then
     415           0 :                write(iulog,*) 'xs_init: error ',istat,' reading ac'
     416           0 :                call endrun
     417             :             end if
     418             :          end do
     419             : 
     420           0 :          read(unit,901)
     421           0 :          do i = 1,20
     422           0 :             read(unit,903,iostat=istat) bc(i,:)
     423           0 :             if( istat /= 0 ) then
     424           0 :                write(iulog,*) 'xs_init: error ',istat,' reading bc'
     425           0 :                call endrun
     426             :             end if
     427             :          end do
     428           0 :          close( unit )
     429           0 :          call freeunit( unit )
     430             : 
     431           0 :       wave_num(17:1:-1) = (/ (48250._r8 + (500._r8*i),i=1,17) /)
     432             : 
     433             :  901  format( / )
     434             :  903  format( 17(e23.14,1x))
     435             : 
     436           0 :       end subroutine xs_init
     437             : 
     438           0 :       subroutine jno_init
     439             : !-------------------------------------------------------------
     440             : !       ... Initialization for no photolysis
     441             : !-------------------------------------------------------------
     442             : 
     443             :       implicit none
     444             : 
     445             : !-------------------------------------------------------------
     446             : !     ... Local variables
     447             : !-------------------------------------------------------------
     448             :       real(r8), dimension(24) :: a, b, c
     449             : 
     450             : !------------------------------------------------------------------------------
     451             : !       ... 6 sub-intervals for O2 5-0 at 265K,
     452             : !           2 sub-sub-intervals for NO 0-0 at 250K
     453             : !------------------------------------------------------------------------------
     454             :       a(:) = (/    0._r8,       0._r8,       0._r8,       0._r8, &
     455             :                    5.12e-02_r8, 5.68e-03_r8, 1.32e-18_r8, 4.41e-17_r8, &
     456             :                    1.36e-01_r8, 1.52e-02_r8, 6.35e-19_r8, 4.45e-17_r8, &
     457             :                    1.65e-01_r8, 1.83e-02_r8, 7.09e-19_r8, 4.50e-17_r8, &
     458             :                    1.41e-01_r8, 1.57e-02_r8, 2.18e-19_r8, 2.94e-17_r8, &
     459           0 :                    4.50e-02_r8, 5.00e-03_r8, 4.67e-19_r8, 4.35e-17_r8 /)
     460             : 
     461             : !------------------------------------------------------------------------------
     462             : !       ... sub-intervals for o2 9-0 band,
     463             : !           2 sub-sub-intervals for no 1-0 at 250 k
     464             : !------------------------------------------------------------------------------
     465             :       b(:) = (/        0._r8,       0._r8,       0._r8,       0._r8, &
     466             :                        0._r8,       0._r8,       0._r8,       0._r8, &
     467             :                  1.93e-03_r8, 2.14e-04_r8, 3.05e-21_r8, 3.20e-21_r8, &
     468             :                  9.73e-02_r8, 1.08e-02_r8, 5.76e-19_r8, 5.71e-17_r8, &
     469             :                  9.75e-02_r8, 1.08e-02_r8, 2.29e-18_r8, 9.09e-17_r8, &
     470           0 :                  3.48e-02_r8, 3.86e-03_r8, 2.21e-18_r8, 6.00e-17_r8 /)
     471             : 
     472             : !------------------------------------------------------------------------------
     473             : !       ... sub-intervals for o2 10-0 band,
     474             : !           2 sub-sub-intervals for no 1-0 at 250 k
     475             : !------------------------------------------------------------------------------
     476             :       c(:) = (/  4.50e-02_r8, 5.00e-03_r8, 1.80e-18_r8, 1.40e-16_r8, &
     477             :                  1.80e-01_r8, 2.00e-02_r8, 1.50e-18_r8, 1.52e-16_r8, &
     478             :                  2.25e-01_r8, 2.50e-02_r8, 5.01e-19_r8, 7.00e-17_r8, &
     479             :                  2.25e-01_r8, 2.50e-02_r8, 7.20e-20_r8, 2.83e-17_r8, &
     480             :                  1.80e-01_r8, 2.00e-02_r8, 6.72e-20_r8, 2.73e-17_r8, &
     481           0 :                  4.50e-02_r8, 5.00e-03_r8, 1.49e-21_r8, 6.57e-18_r8 /)
     482             : 
     483           0 :       wtno50 (1:6,1) = a(1:24:4)
     484           0 :       wtno50 (1:6,2) = a(2:24:4)
     485           0 :       csno50 (1:6,1) = a(3:24:4)
     486           0 :       csno50 (1:6,2) = a(4:24:4)
     487           0 :       wtno90 (1:6,1) = b(1:24:4)
     488           0 :       wtno90 (1:6,2) = b(2:24:4)
     489           0 :       csno90 (1:6,1) = b(3:24:4)
     490           0 :       csno90 (1:6,2) = b(4:24:4)
     491           0 :       wtno100(1:6,1) = c(1:24:4)
     492           0 :       wtno100(1:6,2) = c(2:24:4)
     493           0 :       csno100(1:6,1) = c(3:24:4)
     494           0 :       csno100(1:6,2) = c(4:24:4)
     495             : 
     496           0 :       end subroutine jno_init
     497             : 
     498           0 :       subroutine jshort_timestep_init
     499             : !---------------------------------------------------------------
     500             : !       ... set etfphot if required
     501             : !---------------------------------------------------------------
     502             : 
     503             :       use mo_util,        only : rebin
     504             :       use solar_irrad_data,     only : data_nbins=>nbins, data_we => we, data_etf => sol_etf
     505             : 
     506             :       implicit none
     507             : 
     508           0 :       call rebin( data_nbins, nw,      data_we, we,    data_etf, etfphot )
     509           0 :       call rebin( data_nbins, nw_ms93, data_we, we_ms, data_etf, etfphot_ms93 )
     510             : 
     511           0 :       end subroutine jshort_timestep_init
     512             : 
     513           0 :       subroutine jshort_hrates( nlev, zen, o2_vmr, o3_vmr, o2cc, &
     514           0 :                                 o3cc, tlev, zkm, mw, qrs, cparg, &
     515           0 :                                 lchnk, long, co2cc, scco2, do_diag )
     516             : !==============================================================================!
     517             : !   Subroutine Jshort                                                          !
     518             : !==============================================================================!
     519             : !   Purpose:                                                                   !
     520             : !     To calculate thermal heating rates for lamba < 200 nm
     521             : !==============================================================================!
     522             : !   This routine uses JO2 parameterizations based on:                          !
     523             : !        Lyman alpha... Chabrillat and Kockarts, GRL, 25, 2659, 1998           !
     524             : !        SRC .......... Brasseur and Solomon, 1986 (from TUV)                  !
     525             : !        SRB .......... Koppers and Murtagh, Ann. Geophys., 14, 68-79, 1996    !
     526             : !                        (supplied by Dan Marsh, NCAR ACD                      !
     527             : !   and JNO:                                                                   !
     528             : !        SRB .......... Minschwanner and Siskind, JGR< 98, 20401, 1993.        !
     529             : !==============================================================================!
     530             : !   Input:                                                                     !
     531             : !       o2cc....... O2 concentration, molecule cm-3                            !
     532             : !       o3cc....... O3 concentration, molecule cm-3                            !
     533             : !     zen........ zenith angle, units = degrees                                !
     534             : !     tlev....... Temperature Profile (K)                                      !
     535             : !     zkm ....... Altitude, km                                                 !
     536             : !                                                                              !
     537             : !   Output:                                                                    !
     538             : !     qrs ... short wavelength thermal heating rates
     539             : !==============================================================================!
     540             : !                                                                              !
     541             : !   Approach:                                                                  !
     542             : !                                                                              !
     543             : !    1) Call sphers (taken from TUV)                                           !
     544             : !         -> derives dsdh and nid used in slant column routines                !
     545             : !         -> zenith angle dependent                                            !
     546             : !                                                                              !
     547             : !    2) Call  slant_col (taken from TUV)                                       !
     548             : !               -> derives the slant column for each species                   !
     549             : !                                                                              !
     550             : !    3) Calls get_crs                                                          !
     551             : !               -> read a NetCDF file                                          !
     552             : !               -> returns cross sections*quantum yields for all species that  !
     553             : !                  have absorption below 200nm.                                !
     554             : !                                                                              !
     555             : !    4) Derives transmission and photolysis rates for selective species        !
     556             : !                                                                              !
     557             : !==============================================================================!
     558             : !   EDIT HISTORY:                                                              !
     559             : !   Created by Doug Kinnison, 3/14/2002                                        !
     560             : !==============================================================================!
     561             : 
     562           0 :        use physconst,       only : avogad
     563             :        use error_messages, only : alloc_err
     564             : 
     565             :        implicit none
     566             : 
     567             :        integer, parameter  :: branch = 2           ! two photolysis pathways for JO2
     568             :        real(r8), parameter :: km2cm  = 1.e5_r8
     569             : 
     570             : !------------------------------------------------------------------------------
     571             : !     ... dummy arguments
     572             : !------------------------------------------------------------------------------
     573             :        integer, intent(in)     :: nlev                 ! model vertical levels
     574             :        integer, intent(in)     :: lchnk                ! chunk index
     575             :        integer, intent(in)     :: long                 ! chunk index
     576             :        real(r8), intent(in)    :: zen                  ! Zenith angle (degrees)
     577             :        real(r8), intent(in)    :: o2_vmr(nlev)         ! o2 conc (mol/mol)
     578             :        real(r8), intent(in)    :: o3_vmr(nlev)         ! o3 conc (mol/mol)
     579             :        real(r8), intent(in)    :: o2cc(nlev)           ! o2 conc (mol/cm^3)
     580             :        real(r8), intent(in)    :: co2cc(nlev)          ! co2 conc (mol/cm^3)
     581             :        real(r8), intent(in)    :: o3cc(nlev)           ! o3 conc (mol/cm^3)
     582             :        real(r8), intent(in)    :: tlev(nlev)           ! Temperature profile
     583             :        real(r8), intent(in)    :: zkm(nlev)            ! Altitude, km
     584             :        real(r8), intent(in)    :: mw(nlev)             ! atms molecular weight
     585             :        real(r8), intent(in)    :: cparg(nlev)          ! column specific heat capacity
     586             :        real(r8), intent(inout) :: qrs(:,:)             ! sw heating rates
     587             :        real(r8), intent(out)   :: scco2(nlev)          ! co2 column concentration (molec/cm^2)
     588             :        logical,  intent(in)    :: do_diag
     589             : 
     590             : !------------------------------------------------------------------------------
     591             : !     ... local variables
     592             : !------------------------------------------------------------------------------
     593             :        integer :: k, k1                     ! Altitude indicies
     594             :        integer :: wn                        ! Wavelength index
     595             :        integer :: astat
     596           0 :        integer :: nid(0:nlev)               ! Number of layers crossed by the direct
     597             :                                             ! beam when travelling from the top of the
     598             :                                             ! atmosphere to layer i; NID(i), i = 0..NZ-1
     599             :        real(r8) :: hfactor
     600           0 :        real(r8) :: dsdh(0:nlev,nlev)        ! Slant path of direct beam through each
     601             :                                             ! layer crossed  when travelling from the top of
     602             :                                             ! the atmosphere to layer i; DSDH(i,j), i = 0.
     603             :                                             ! NZ-1, j = 1..NZ-1   (see sphers.f)
     604           0 :        real(r8), allocatable :: fnorm(:,:)      ! Normalized ETF
     605           0 :        real(r8), allocatable :: trans_o2(:,:)   ! Transmission o2 (total)
     606           0 :        real(r8), allocatable :: trans_o3(:,:)   ! Transmission, ozone
     607           0 :        real(r8), allocatable :: wrk(:)      ! wrk array
     608           0 :        real(r8) :: jo2_lya(nlev)            ! Total photolytic rate constant for Ly alpha
     609             :        real(r8) :: jo2_srb(nlev)            ! Total JO2  for SRB
     610             :        real(r8) :: jo2_src(nlev)            ! Total JO2 for SRC
     611           0 :        real(r8) :: delz(nlev)               ! layer thickness (cm)
     612           0 :        real(r8) :: o2scol(nlev)             ! O2 Slant Column
     613           0 :        real(r8) :: o3scol(nlev)             ! O3 Slant Column
     614           0 :        real(r8) :: rmla(nlev)               ! Transmission, Lyman Alpha (other species)
     615           0 :        real(r8) :: ro2la(nlev)              ! Transmission, Lyman Alpha (for JO2)
     616           0 :        real(r8) :: tlevmin(nlev)
     617           0 :        real(r8) :: abs_col(nlev)
     618           0 :        real(r8) :: tsrb(nlev,nsrbtuv)       ! Transmission in the SRB
     619           0 :        real(r8) :: xs_o2srb(nlev,nsrbtuv)   ! Cross section * QY for O2 in SRB
     620             : 
     621           0 :       allocate( fnorm(nlev,nw),stat=astat )
     622           0 :       if( astat /= 0 ) then
     623           0 :          call alloc_err( astat, 'jshort_hrates', 'fnorm', nw*nlev )
     624             :       end if
     625           0 :       allocate( trans_o2(nlev,nw),stat=astat )
     626           0 :       if( astat /= 0 ) then
     627           0 :          call alloc_err( astat, 'jshort_hrates', 'trans_o2', nw*nlev )
     628             :       end if
     629           0 :       allocate( trans_o3(nlev,nw),stat=astat )
     630           0 :       if( astat /= 0 ) then
     631           0 :          call alloc_err( astat, 'jshort_hrates', 'trans_o3', nw*nlev )
     632             :       end if
     633           0 :       allocate( wrk(nw),stat=astat )
     634           0 :       if( astat /= 0 ) then
     635           0 :          call alloc_err( astat, 'jshort_hrates', 'wrk', nw )
     636             :       end if
     637             : 
     638             : !------------------------------------------------------------------------------
     639             : !     ... derive Slant Path for Spherical Atmosphere
     640             : !------------------------------------------------------------------------------
     641           0 :       call sphers( nlev, zkm, zen, dsdh, nid )
     642             : 
     643             : !------------------------------------------------------------------------------
     644             : !       ... derive O2, O3, and CO2 slant columns
     645             : !------------------------------------------------------------------------------
     646           0 :       delz(1:nlev-1) = km2cm*(zkm(1:nlev-1) - zkm(2:nlev))
     647           0 :       call slant_col( nlev, delz, dsdh, nid, o2cc, o2scol )
     648           0 :       call slant_col( nlev, delz, dsdh, nid, o3cc, o3scol )
     649           0 :       call slant_col( nlev, delz, dsdh, nid, co2cc, scco2 )
     650             : 
     651             : !------------------------------------------------------------------------------
     652             : !       ... transmission due to ozone
     653             : !------------------------------------------------------------------------------
     654           0 :       do wn = 1,nw
     655           0 :          abs_col(:)     = min( (xs_o3a(wn) + xs_o3b(wn))*o3scol(:),100._r8 )
     656           0 :          trans_o3(:,wn) = exp( -abs_col(:) )
     657             :       end do
     658             : 
     659             : !------------------------------------------------------------------------------
     660             : !       ... derive the cross section and transmission for
     661             : !           molecular oxygen Lya, SRC, and SRB's
     662             : !------------------------------------------------------------------------------
     663             : !       ... transmission due to molecular oxygen in the SRC
     664             : !------------------------------------------------------------------------------
     665           0 :       do wn = 1,nsrc_tot
     666           0 :          abs_col(:) = min( xs_o2src(wn)*o2scol(:),100._r8 )
     667           0 :          trans_o2(:,wn) = exp( -abs_col(:) )
     668             :       end do
     669             : 
     670             : !------------------------------------------------------------------------------
     671             : !       ... transmission and cross sections due to O2 at lyman alpha
     672             : !------------------------------------------------------------------------------
     673           0 :       call lymana( nlev, o2scol, rmla, ro2la )
     674             : 
     675             : !------------------------------------------------------------------------------
     676             : !       ... place lya reduction faction in transmission array
     677             : !           this must follow the SRC placement (above)
     678             : !------------------------------------------------------------------------------
     679           0 :       trans_o2(:,1) = rmla(:)
     680             : 
     681             : !------------------------------------------------------------------------------
     682             : !     ... Molecular Oxygen, SRB
     683             : !------------------------------------------------------------------------------
     684             : !     ... Koppers Grid (see Koppers and Murtagh, Ann. Geophys., 14, 68-79, 1996)
     685             : !        #    wl(i)       wl(i+1)
     686             : !        1   174.4        177.0
     687             : !        2   177.0        178.6
     688             : !        3   178.6        180.2
     689             : !        4   180.2        181.8
     690             : !        5   181.8        183.5
     691             : !        6   183.5        185.2
     692             : !        7   185.2        186.9
     693             : !        8   186.9        188.7
     694             : !        9   188.7        190.5
     695             : !        10  190.5        192.3
     696             : !        11  192.3        194.2
     697             : !        12  194.2        196.1
     698             : !        13  196.1        198.0
     699             : !        14  198.0        200.0  <<last wl bin for <200nm
     700             : !        ----------------------
     701             : !        15  200.0        202.0
     702             : !        16  202.0        204.1
     703             : !        17  204.1        205.8
     704             : !------------------------------------------------------------------------------
     705             : 
     706             : !------------------------------------------------------------------------------
     707             : !     ... Kopper SRB parameterization is used here
     708             : !------------------------------------------------------------------------------
     709           0 :       tlevmin(nlev:1:-1) = min( max( tlev(:),150._r8 ),350._r8 )
     710           0 :       call calc_o2srb( nlev, nid, o2scol, tlevmin, tsrb, xs_o2srb )
     711             : 
     712             : !------------------------------------------------------------------------------
     713             : !     ... Place Koppers SRB transmission (1-14) on user
     714             : !         grid #20 (wc=175.7nm)
     715             : !------------------------------------------------------------------------------
     716           0 :       do wn = 1,nsrb_tot
     717           0 :          trans_o2(:,wn+nsrc_tot) = tsrb(:,wn)
     718             :       end do
     719             : 
     720             : !------------------------------------------------------------------------------
     721             : !     ... Derive the normalize flux at each altitude,
     722             : !         corrected for O2 and O3 absorption
     723             : !------------------------------------------------------------------------------
     724           0 :       do wn = 1,nw                                  ! nw = 33 (nsrb_tot+nsrc_tot)
     725           0 :          fnorm(:,wn) = etfphot(wn)*trans_o2(:,wn)*trans_o3(:,wn)
     726             :       end do
     727             : 
     728             : !------------------------------------------------------------------------------
     729             : !     ... Derive the O2 rate constant and apply branching ratio (QY)
     730             : !------------------------------------------------------------------------------
     731             : !     ... SRC and SRB QY
     732             : !         Longward  of 174.65 the product is O2 + hv => O(3P) + O(3P)
     733             : !         Shortward of 174.65 the product is O2 + hv => O(3P) + O(1D)
     734             : !         The QY is assumed to be unity in both wavelength ranges.
     735             : !
     736             : !     ... Lyman Alpha QY
     737             : !         O2 + hv -> O(3P) + O(3P) at Lyman Alpha has a QY = 0.47
     738             : !         O2 + hv -> O(3P) + O(1D) at Lyman Alpha has a QY = 0.53
     739             : !         Lacoursiere et al., J. Chem. Phys. 110., 1949-1958, 1999.
     740             : !------------------------------------------------------------------------------
     741             : !     ... lyman alpha
     742             : !------------------------------------------------------------------------------
     743           0 :       jo2_lya(:) = etfphot(1)*ro2la(:)*wlintv(1)
     744             : 
     745           0 :       wrk(1:nsrc_tot) = xs_o2src(1:nsrc_tot)*wlintv(1:nsrc_tot) &
     746           0 :                                             *bde_o2_a(1:nsrc_tot)
     747           0 :       wrk(1)          = 0._r8
     748             : !------------------------------------------------------------------------------
     749             : !     ... o2 src heating
     750             : !------------------------------------------------------------------------------
     751           0 :       if( do_diag ) then
     752           0 :       write(iulog,*) '-------------------------------------------------'
     753           0 :       write(iulog,*) 'jshort_hrates: fnorm,wrk at long,lchnk = ',long,lchnk
     754           0 :       write(iulog,'(1p,5g12.5)') fnorm(nlev,1:nsrc_tot)
     755           0 :       write(iulog,*) ' '
     756           0 :       write(iulog,'(1p,5g12.5)') wrk(1:nsrc_tot)
     757           0 :       write(iulog,*) '-------------------------------------------------'
     758             :       end if
     759             : #ifdef USE_ESSL
     760             :       call dgemm( 'N', 'N', nlev, 1, nsrc_tot, &
     761             :                   1._r8, fnorm, nlev, wrk, nw, &
     762             :                   0._r8, qrs, nlev )
     763             : #else
     764           0 :       qrs(:,1) = matmul( fnorm(:,1:nsrc_tot),wrk(1:nsrc_tot) )
     765             : #endif
     766             : !------------------------------------------------------------------------------
     767             : !     ... o2 srb heating
     768             : !------------------------------------------------------------------------------
     769           0 :       do k = 1,nlev
     770           0 :          wrk(1:nsrb_tot) = xs_o2srb(k,1:nsrb_tot)*wlintv(nsrc_tot+1:nsrc_tot+nsrb_tot) &
     771           0 :                                                  *bde_o2_b(nsrc_tot+1:nsrc_tot+nsrb_tot)
     772           0 :          qrs(k,2)        = dot_product( fnorm(k,nsrc_tot+1:nsrc_tot+nsrb_tot),wrk(1:nsrb_tot) )
     773             :       end do
     774             : 
     775           0 :       if( do_diag ) then
     776           0 :       write(iulog,*) '-------------------------------------------------'
     777           0 :       write(iulog,*) 'jshort_hrates: lya,bde_o2_a,qrs(nlev) at long,lchnk = ',long,lchnk
     778           0 :       write(iulog,'(1p,5g12.5)') jo2_lya(nlev),bde_o2_a(2),qrs(nlev,1)
     779           0 :       write(iulog,*) '-------------------------------------------------'
     780             :       end if
     781             : !------------------------------------------------------------------------------
     782             : !     ... total o2 heating
     783             : !------------------------------------------------------------------------------
     784             : !------------------------------------------------------------------------------
     785             : !     ... Branch 1, O2 + hv => O(3P) + O(3P); wavelengths >175nm
     786             : !------------------------------------------------------------------------------
     787           0 :       qrs(:,2)  = qrs(:,2) + jo2_lya(:)*.47_r8*bde_o2_b(2)
     788             : !------------------------------------------------------------------------------
     789             : !     ... Branch 2, O2 + hv => O(3P) + O(1D);  wavelengths <175nm
     790             : !------------------------------------------------------------------------------
     791           0 :       qrs(:,1)  = qrs(:,1) + jo2_lya(:)*.53_r8*bde_o2_a(2)
     792           0 :       if( do_diag ) then
     793           0 :       write(iulog,*) '-------------------------------------------------'
     794           0 :       write(iulog,*) 'jshort_hrates: o2(1),qrs(nlev) at long,lchnk = ',long,lchnk
     795           0 :       write(iulog,'(1p,5g12.5)') o2_vmr(1),qrs(nlev,1)
     796           0 :       write(iulog,*) '-------------------------------------------------'
     797             :       end if
     798             : 
     799             : !------------------------------------------------------------------------------
     800             : !       ... the o3 heating rates
     801             : !------------------------------------------------------------------------------
     802           0 :       wrk(:) = xs_o3a(:)*wlintv(:)*bde_o3_a(:)
     803             : #ifdef USE_ESSL
     804             :       call dgemm( 'N', 'N', nlev, 1, nw, &
     805             :                   1._r8, fnorm, nlev, wrk, nw, &
     806             :                   0._r8, qrs(1,3), nlev )
     807             : #else
     808           0 :       qrs(:,3) = matmul( fnorm,wrk )
     809             : #endif
     810           0 :       wrk(:) = xs_o3b(:)*wlintv(:)*bde_o3_b(:)
     811             : #ifdef USE_ESSL
     812             :       call dgemm( 'N', 'N', nlev, 1, nw, &
     813             :                   1._r8, fnorm, nlev, wrk, nw, &
     814             :                   0._r8, qrs(1,4), nlev )
     815             : #else
     816           0 :       qrs(:,4) = matmul( fnorm,wrk )
     817             : #endif
     818             : 
     819             : !------------------------------------------------------------------------------
     820             : !       ... form actual heating rates (k/s)
     821             : !------------------------------------------------------------------------------
     822           0 :       do k = 1,nlev
     823           0 :          k1       = nlev - k + 1
     824           0 :          hfactor  = avogad/(cparg(k1)*mw(k1))
     825           0 :          qrs(k,1) = qrs(k,1)*hfactor*o2_vmr(k1)
     826           0 :          qrs(k,2) = qrs(k,2)*hfactor*o2_vmr(k1)
     827           0 :          qrs(k,3) = qrs(k,3)*hfactor*o3_vmr(k1)
     828           0 :          qrs(k,4) = qrs(k,4)*hfactor*o3_vmr(k1)
     829             :       end do
     830             : 
     831           0 :       deallocate( fnorm, trans_o2, trans_o3, wrk )
     832             : 
     833           0 :       end subroutine jshort_hrates
     834             : 
     835           0 :       subroutine jshort_photo( nlev, zen, n2cc, o2cc, o3cc, &
     836           0 :                                nocc, tlev, zkm, jo2_sht, jno_sht, jsht )
     837             : !==============================================================================!
     838             : !   Subroutine Jshort                                                          !
     839             : !                                                                              !
     840             : !==============================================================================!
     841             : !   Purpose:                                                                   !
     842             : !     To calculate the total J for JO2, JNO, and selective species below 200nm.!
     843             : !                                                                              !
     844             : !==============================================================================!
     845             : !   This routine uses JO2 parameterizations based on:                          !
     846             : !        Lyman alpha... Chabrillat and Kockarts, GRL, 25, 2659, 1998           !
     847             : !        SRC .......... Brasseur and Solomon, 1986 (from TUV)                  !
     848             : !        SRB .......... Koppers and Murtagh, Ann. Geophys., 14, 68-79, 1996    !
     849             : !                        (supplied by Dan Marsh, NCAR ACD                      !
     850             : !   and JNO:                                                                   !
     851             : !        SRB .......... Minschwanner and Siskind, JGR< 98, 20401, 1993.        !
     852             : !                                                                              !
     853             : !==============================================================================!
     854             : !   Input:                                                                     !
     855             : !       n2cc....... N2 concentration, molecule cm-3                            !
     856             : !       o2cc....... O2 concentration, molecule cm-3                            !
     857             : !       o3cc....... O3 concentration, molecule cm-3                            !
     858             : !       nocc....... NO concentration, molecule cm-3                            !
     859             : !       n2cc....... N2 concentration, molecule cm-3                            !
     860             : !     zen........ zenith angle, units = degrees                                !
     861             : !     tlev....... Temperature Profile (K)                                      !
     862             : !     zkm ....... Altitude, km                                                 !
     863             : !                                                                              !
     864             : !   Output:                                                                    !
     865             : !     jo2_sht ... O2 photolytic rate constant, sec-1, <200nm                   !
     866             : !     jno_sht ... NO photolytic rate constant, sec-1, SRB                      !
     867             : !     jsht. Photolytic rate constant for other species below 200nm             !
     868             : !                                                                              !
     869             : !==============================================================================!
     870             : !                                                                              !
     871             : !   Approach:                                                                  !
     872             : !                                                                              !
     873             : !    1) Call sphers (taken from TUV)                                           !
     874             : !         -> derives dsdh and nid used in slant column routines                !
     875             : !         -> zenith angle dependent                                            !
     876             : !                                                                              !
     877             : !    2) Call  slant_col (taken from TUV)                                       !
     878             : !               -> derives the slant column for each species                   !
     879             : !                                                                              !
     880             : !    3) Calls get_crs                                                          !
     881             : !               -> read a NetCDF file                                          !
     882             : !               -> returns cross sections*quantum yields for all species that  !
     883             : !                  have absorption below 200nm.                                !
     884             : !                                                                              !
     885             : !    4) Derives transmission and photolysis rates for selective species        !
     886             : !                                                                              !
     887             : !==============================================================================!
     888             : !   EDIT HISTORY:                                                              !
     889             : !   Created by Doug Kinnison, 3/14/2002                                        !
     890             : !==============================================================================!
     891             : 
     892             :         use error_messages, only : alloc_err
     893             : 
     894             :         implicit none
     895             : 
     896             :         integer, parameter :: branch      = 2       ! two photolysis pathways for JO2
     897             :         real(r8), parameter    :: km2cm   = 1.e5_r8
     898             : 
     899             : !------------------------------------------------------------------------------
     900             : !     ... dummy arguments
     901             : !------------------------------------------------------------------------------
     902             :         integer, intent(in)     :: nlev                 ! model vertical levels
     903             :         real(r8), intent(in)    :: zen                  ! Zenith angle (degrees)
     904             :         real(r8), intent(in)    :: n2cc(nlev)           ! Molecular Nitrogen conc (mol/cm^3)
     905             :         real(r8), intent(in)    :: o2cc(nlev)           ! Molecular Oxygen conc (mol/cm^3)
     906             :         real(r8), intent(in)    :: o3cc(nlev)           ! Ozone concentration (mol/cm^3)
     907             :         real(r8), intent(in)    :: nocc(nlev)           ! Nitric Oxide conc (mol/cm^3)
     908             :         real(r8), intent(in)    :: tlev(nlev)           ! Temperature profile
     909             :         real(r8), intent(in)    :: zkm(nlev)            ! Altitude, km
     910             :         real(r8), intent(out)   :: jo2_sht(nlev,branch) ! JO2, sec-1, <200nm
     911             :         real(r8), intent(out)   :: jno_sht(nlev)        ! JNO, sec-1, SRB
     912             :         real(r8), intent(out)   :: jsht(:,:)            ! Additional J's
     913             : 
     914             : !------------------------------------------------------------------------------
     915             : !     ... local variables
     916             : !------------------------------------------------------------------------------
     917             :         integer :: k                         ! Altitude index
     918             :         integer :: wn                        ! Wavelength index
     919             :         integer :: astat
     920           0 :         integer :: nid(0:nlev)               ! Number of layers crossed by the direct
     921             :                                              ! beam when travelling from the top of the
     922             :                                              ! atmosphere to layer i; NID(i), i = 0..NZ-1
     923             :         real(r8) :: hfactor
     924           0 :         real(r8) :: dsdh(0:nlev,nlev)        ! Slant path of direct beam through each
     925             :                                              ! layer crossed  when travelling from the top of
     926             :                                              ! the atmosphere to layer i; DSDH(i,j), i = 0.
     927             :                                              ! NZ-1, j = 1..NZ-1   (see sphers.f)
     928           0 :         real(r8), allocatable :: fnorm(:,:)      ! Normalized ETF
     929           0 :         real(r8), allocatable :: trans_o2(:,:)   ! Transmission o2 (total)
     930           0 :         real(r8), allocatable :: trans_o3(:,:)   ! Transmission, ozone
     931           0 :         real(r8), allocatable :: wrk(:)      ! wrk array
     932           0 :         real(r8) :: jo2_lya(nlev)            ! Total photolytic rate constant for Ly alpha
     933           0 :         real(r8) :: jo2_srb(nlev)            ! Total JO2  for SRB
     934           0 :         real(r8) :: jo2_src(nlev)            ! Total JO2 for SRC
     935           0 :         real(r8) :: delz(nlev)               ! layer thickness (cm)
     936           0 :         real(r8) :: o2scol(nlev)             ! O2 Slant Column
     937           0 :         real(r8) :: o3scol(nlev)             ! O3 Slant Column
     938           0 :         real(r8) :: noscol(nlev)             ! NO Slant Column
     939           0 :         real(r8) :: rmla(nlev)               ! Transmission, Lyman Alpha (other species)
     940           0 :         real(r8) :: ro2la(nlev)              ! Transmission, Lyman Alpha (for JO2)
     941           0 :         real(r8) :: tlevmin(nlev)
     942           0 :         real(r8) :: abs_col(nlev)
     943           0 :         real(r8) :: tsrb(nlev,nsrbtuv)       ! Transmission in the SRB
     944           0 :         real(r8) :: xs_o2srb(nlev,nsrbtuv)   ! Cross section * QY for O2 in SRB
     945             : 
     946           0 :       allocate( fnorm(nlev,nw),stat=astat )
     947           0 :       if( astat /= 0 ) then
     948           0 :          call alloc_err( astat, 'jshort_photo', 'fnorm', nw*nlev )
     949             :       end if
     950           0 :       allocate( trans_o2(nlev,nw),stat=astat )
     951           0 :       if( astat /= 0 ) then
     952           0 :          call alloc_err( astat, 'jshort_photo', 'trans_o2', nw*nlev )
     953             :       end if
     954           0 :       allocate( trans_o3(nlev,nw),stat=astat )
     955           0 :       if( astat /= 0 ) then
     956           0 :          call alloc_err( astat, 'jshort_photo', 'trans_o3', nw*nlev )
     957             :       end if
     958           0 :       allocate( wrk(nw),stat=astat )
     959           0 :       if( astat /= 0 ) then
     960           0 :          call alloc_err( astat, 'jshort_photo', 'wrk', nw )
     961             :       end if
     962             : 
     963             : !------------------------------------------------------------------------------
     964             : !     ... Derive Slant Path for Spherical Atmosphere
     965             : !------------------------------------------------------------------------------
     966           0 :       call sphers( nlev, zkm, zen, dsdh, nid )
     967             : 
     968             : !------------------------------------------------------------------------------
     969             : !     ... Derive O2, O3, and NO Slant Column
     970             : !------------------------------------------------------------------------------
     971           0 :       delz(1:nlev-1) = km2cm*(zkm(1:nlev-1) - zkm(2:nlev))
     972           0 :       call slant_col( nlev, delz, dsdh, nid, o2cc, o2scol )
     973           0 :       call slant_col( nlev, delz, dsdh, nid, o3cc, o3scol )
     974           0 :       call slant_col( nlev, delz, dsdh, nid, nocc, noscol )
     975             : 
     976             : !------------------------------------------------------------------------------
     977             : !     ... Transmission due to ozone
     978             : !------------------------------------------------------------------------------
     979           0 :       do wn = 1,nw
     980           0 :          abs_col(:)     = min( (xs_o3a(wn) + xs_o3b(wn))*o3scol(:),100._r8 )
     981           0 :          trans_o3(:,wn) = exp( -abs_col(:) )
     982             :       end do
     983             : 
     984             : !------------------------------------------------------------------------------
     985             : !    ... Derive the cross section and transmission for
     986             : !        molecular oxygen Lya, SRC, and SRB's
     987             : !------------------------------------------------------------------------------
     988             : !------------------------------------------------------------------------------
     989             : !     ... Transmission due to molecular oxygen in the SRC
     990             : !------------------------------------------------------------------------------
     991           0 :       do wn = 1,nsrc_tot
     992           0 :          abs_col(:) = min( xs_o2src(wn)*o2scol(:),100._r8 )
     993           0 :          trans_o2(:,wn) = exp( -abs_col(:) )
     994             :       end do
     995             : 
     996             : !------------------------------------------------------------------------------
     997             : !     ... Transmission and cross sections due to O2 at lyman alpha
     998             : !------------------------------------------------------------------------------
     999           0 :       call lymana( nlev, o2scol, rmla, ro2la )
    1000             : 
    1001             : !------------------------------------------------------------------------------
    1002             : !    ... Place lya reduction faction in transmission array
    1003             : !    ... This must follow the SRC placement (above)
    1004             : !------------------------------------------------------------------------------
    1005           0 :       trans_o2(:,1) = rmla(:)
    1006             : 
    1007             : !------------------------------------------------------------------------------
    1008             : !     ... Molecular Oxygen, SRB
    1009             : !------------------------------------------------------------------------------
    1010             : !     ... Koppers Grid (see Koppers and Murtagh, Ann. Geophys., 14, 68-79, 1996)
    1011             : !        #    wl(i)       wl(i+1)
    1012             : !        1   174.4        177.0
    1013             : !        2   177.0        178.6
    1014             : !        3   178.6        180.2
    1015             : !        4   180.2        181.8
    1016             : !        5   181.8        183.5
    1017             : !        6   183.5        185.2
    1018             : !        7   185.2        186.9
    1019             : !        8   186.9        188.7
    1020             : !        9   188.7        190.5
    1021             : !        10  190.5        192.3
    1022             : !        11  192.3        194.2
    1023             : !        12  194.2        196.1
    1024             : !        13  196.1        198.0
    1025             : !        14  198.0        200.0  <<last wl bin for <200nm
    1026             : !        ----------------------
    1027             : !        15  200.0        202.0
    1028             : !        16  202.0        204.1
    1029             : !        17  204.1        205.8
    1030             : !------------------------------------------------------------------------------
    1031             : 
    1032             : !------------------------------------------------------------------------------
    1033             : !     ... Kopper SRB parameterization is used here
    1034             : !------------------------------------------------------------------------------
    1035           0 :       tlevmin(nlev:1:-1) = min( max( tlev(:),150._r8 ),350._r8 )
    1036           0 :       call calc_o2srb( nlev, nid, o2scol, tlevmin, tsrb, xs_o2srb )
    1037             : 
    1038             : !------------------------------------------------------------------------------
    1039             : !     ... Place Koppers SRB transmission (1-14) on user
    1040             : !         grid #20 (wc=175.7nm)
    1041             : !------------------------------------------------------------------------------
    1042           0 :       do wn = 1,nsrb_tot
    1043           0 :          trans_o2(:,wn+nsrc_tot) = tsrb(:,wn)
    1044             :       end do
    1045             : 
    1046             : !------------------------------------------------------------------------------
    1047             : !     ... Derive the normalize flux at each altitude,
    1048             : !         corrected for O2 and O3 absorption
    1049             : !------------------------------------------------------------------------------
    1050           0 :       do wn = 1,nw                               ! nw = 33 (nsrb_tot+nsrc_tot)
    1051           0 :          fnorm(:,wn) = etfphot(wn)*trans_o2(:,wn)*trans_o3(:,wn)
    1052             :       end do
    1053             : 
    1054             : !------------------------------------------------------------------------------
    1055             : !     ... Derive the O2 rate constant and apply branching ratio (QY)
    1056             : !------------------------------------------------------------------------------
    1057             : !     ... SRC and SRB QY
    1058             : !         Longward  of 174.65 the product is O2 + hv => O(3P) + O(3P)
    1059             : !         Shortward of 174.65 the product is O2 + hv => O(3P) + O(1D)
    1060             : !         The QY is assumed to be unity in both wavelength ranges.
    1061             : !
    1062             : !     ... Lyman Alpha QY
    1063             : !         O2 + hv -> O(3P) + O(3P) at Lyman Alpha has a QY = 0.47
    1064             : !         O2 + hv -> O(3P) + O(1D) at Lyman Alpha has a QY = 0.53
    1065             : !         Lacoursiere et al., J. Chem. Phys. 110., 1949-1958, 1999.
    1066             : !------------------------------------------------------------------------------
    1067             : !     ... Lyman Alpha
    1068             : !------------------------------------------------------------------------------
    1069           0 :       jo2_lya(:) = etfphot(1)*ro2la(:)*wlintv(1)
    1070             : 
    1071           0 :       wrk(1:nsrc_tot) = xs_o2src(1:nsrc_tot)*wlintv(1:nsrc_tot)
    1072           0 :       wrk(1)          = 0._r8
    1073             : !------------------------------------------------------------------------------
    1074             : !     ... o2 src photolysis
    1075             : !------------------------------------------------------------------------------
    1076             : #ifdef USE_ESSL
    1077             :       call dgemm( 'N', 'N', nlev, 1, nsrc_tot, &
    1078             :                   1._r8, fnorm, nlev, wrk, nw, &
    1079             :                   0._r8, jo2_src, nlev )
    1080             : #else
    1081           0 :       jo2_src(:) = matmul( fnorm(:,1:nsrc_tot),wrk(1:nsrc_tot) )
    1082             : #endif
    1083             : !------------------------------------------------------------------------------
    1084             : !     ... o2 srb photolysis
    1085             : !------------------------------------------------------------------------------
    1086           0 :       do k = 1,nlev
    1087           0 :          wrk(1:nsrb_tot) = xs_o2srb(k,1:nsrb_tot)*wlintv(nsrc_tot+1:nsrc_tot+nsrb_tot)
    1088           0 :          jo2_srb(k)      = dot_product( fnorm(k,nsrc_tot+1:nsrc_tot+nsrb_tot),wrk(1:nsrb_tot) )
    1089             :       end do
    1090             : 
    1091             : !------------------------------------------------------------------------------
    1092             : !     ... total o2 photolysis
    1093             : !------------------------------------------------------------------------------
    1094             : !------------------------------------------------------------------------------
    1095             : !     ... Branch 1, O2 + hv => O(3P) + O(3P); wavelengths >175nm
    1096             : !------------------------------------------------------------------------------
    1097           0 :       jo2_sht(:,1) = jo2_lya(:)*.47_r8 + jo2_srb(:)
    1098             : !------------------------------------------------------------------------------
    1099             : !     ... Branch 2, O2 + hv => O(3P) + O(1D);  wavelengths <175nm
    1100             : !------------------------------------------------------------------------------
    1101           0 :       jo2_sht(:,2) = jo2_lya(:)*.53_r8 + jo2_src(:)
    1102             : 
    1103             : !------------------------------------------------------------------------------
    1104             : !     ... Derive the NO rate constant Minsch. and Siskind, JGR, 98, 20401, 1993
    1105             : !------------------------------------------------------------------------------
    1106             :       call calc_jno( nlev, etfphot_ms93, n2cc, o2scol, o3scol, &
    1107           0 :                      noscol, jno_sht )
    1108             : 
    1109             : !------------------------------------------------------------------------------
    1110             : !    ... Derive addtional rate constants for species with wl < 200 nm.!
    1111             : !        Temperature dependence of the cross sections are not included in this
    1112             : !        version.
    1113             : !------------------------------------------------------------------------------
    1114             : #if defined USE_ESSL
    1115             :       call dgemm( 'N', 'N', nlev, nj, nw, &
    1116             :                   1._r8, fnorm, nlev, xs_wl, nw, &
    1117             :                   0._r8, jsht, nlev )
    1118             : #else
    1119           0 :       jsht(:,:) = matmul( fnorm,xs_wl )
    1120             : #endif
    1121             : 
    1122           0 :       deallocate( fnorm, trans_o2, trans_o3, wrk )
    1123             : 
    1124           0 :       end subroutine jshort_photo
    1125             : 
    1126           0 :       subroutine sphers( nlev, z, zenith_angle, dsdh, nid )
    1127             : !=============================================================================!
    1128             : !   Subroutine sphers                                                         !
    1129             : !=============================================================================!
    1130             : !   PURPOSE:                                                                  !
    1131             : !   Calculate slant path over vertical depth ds/dh in spherical geometry.     !
    1132             : !   Calculation is based on:  A.Dahlback, and K.Stamnes, A new spheric model  !
    1133             : !   for computing the radiation field available for photolysis and heating    !
    1134             : !   at twilight, Planet.Space Sci., v39, n5, pp. 671-683, 1991 (Appendix B)   !
    1135             : !=============================================================================!
    1136             : !   PARAMETERS:                                                               !
    1137             : !   NZ      - INTEGER, number of specified altitude levels in the working (I) !
    1138             : !             grid                                                            !
    1139             : !   Z       - REAL, specified altitude working grid (km)                  (I) !
    1140             : !   ZEN     - REAL, solar zenith angle (degrees)                          (I) !
    1141             : !   DSDH    - REAL, slant path of direct beam through each layer crossed  (O) !
    1142             : !             when travelling from the top of the atmosphere to layer i;      !
    1143             : !             DSDH(i,j), i = 0..NZ-1, j = 1..NZ-1                             !
    1144             : !   NID     - INTEGER, number of layers crossed by the direct beam when   (O) !
    1145             : !             travelling from the top of the atmosphere to layer i;           !
    1146             : !             NID(i), i = 0..NZ-1                                             !
    1147             : !=============================================================================!
    1148             : !   EDIT HISTORY:                                                             !
    1149             : !   Original: Taken By Doug Kinnison from Sasha Madronich, TUV Code, V4.1a,   !
    1150             : !             on 1/1/02                                                       !
    1151             : !=============================================================================!
    1152             : 
    1153             :         use physconst,    only : rearth
    1154             : 
    1155             :       implicit none
    1156             : 
    1157             : !------------------------------------------------------------------------------
    1158             : !       ... Dummy arguments
    1159             : !------------------------------------------------------------------------------
    1160             :       integer, intent(in)  :: nlev              ! number model vertical levels
    1161             :       integer, intent(out) :: nid(0:nlev)       ! see above
    1162             :       real(r8), intent (in) :: zenith_angle             ! zenith_angle
    1163             :       real(r8), intent (in) :: z(nlev)          ! geometric altitude (km)
    1164             :       real(r8), intent (out) :: dsdh(0:nlev,nlev)   ! see above
    1165             : 
    1166             : 
    1167             : !------------------------------------------------------------------------------
    1168             : !       ... Local variables
    1169             : !------------------------------------------------------------------------------
    1170             :       real(r8) :: radius
    1171             :       real(r8) :: re
    1172             :       real(r8) :: zenrad
    1173             :       real(r8) :: rpsinz
    1174             :       real(r8) :: const0
    1175             :       real(r8) :: rj
    1176             :       real(r8) :: rjp1
    1177             :       real(r8) :: dsj
    1178             :       real(r8) :: dhj
    1179             :       real(r8) :: ga
    1180             :       real(r8) :: gb
    1181             :       real(r8) :: sm
    1182           0 :       real(r8) :: zd(0:nlev-1)
    1183             : 
    1184             :       integer :: i
    1185             :       integer :: j
    1186             :       integer :: k
    1187             :       integer :: id
    1188             :       integer :: nlayer
    1189             : 
    1190             : 
    1191           0 :       radius = rearth*1.e-3_r8   ! radius earth (km)
    1192             : 
    1193             : !------------------------------------------------------------------------------
    1194             : !       ... set zenith angle in radians
    1195             : !------------------------------------------------------------------------------
    1196           0 :       zenrad = zenith_angle*d2r
    1197           0 :       const0 = sin( zenrad )
    1198             : 
    1199             : !------------------------------------------------------------------------------
    1200             : !       ... set number of layers:
    1201             : !------------------------------------------------------------------------------
    1202           0 :       nlayer = nlev - 1
    1203             : 
    1204             : !------------------------------------------------------------------------------
    1205             : !       ... include the elevation above sea level to the radius of the earth:
    1206             : !------------------------------------------------------------------------------
    1207           0 :       re = radius + z(nlev)
    1208             : 
    1209             : !------------------------------------------------------------------------------
    1210             : !       ... inverse coordinate of z
    1211             : !------------------------------------------------------------------------------
    1212           0 :       do k = 0,nlayer
    1213           0 :         zd(k) = z(k+1) - z(nlev)
    1214             :       end do
    1215             : 
    1216             : !------------------------------------------------------------------------------
    1217             : !       ... initialize dsdh(i,j), nid(i)
    1218             : !------------------------------------------------------------------------------
    1219           0 :       nid(:) = 0
    1220           0 :       do j = 1,nlev
    1221           0 :         dsdh(:,j) = 0._r8
    1222             :       end do
    1223             : 
    1224             : !------------------------------------------------------------------------------
    1225             : !       ... calculate ds/dh of every layer
    1226             : !------------------------------------------------------------------------------
    1227           0 :       do i = 0,nlayer
    1228           0 :         rpsinz = (re + zd(i)) * const0
    1229           0 :         if( zenith_angle <= 90._r8 .or. rpsinz >= re ) then
    1230             : !------------------------------------------------------------------------------
    1231             : ! Find index of layer in which the screening height lies
    1232             : !------------------------------------------------------------------------------
    1233           0 :            id = i
    1234           0 :            if( zenith_angle > 90._r8 ) then
    1235           0 :               do j = 1,nlayer
    1236           0 :                  if( rpsinz < (zd(j-1) + re) .and.  rpsinz >= (zd(j) + re) ) then
    1237             :                     id = j
    1238             :                     exit
    1239             :                  end if
    1240             :               end do
    1241             :            end if
    1242             : 
    1243           0 :            do j = 1,id
    1244           0 :              sm = 1._r8
    1245           0 :              if( j == id .and. id == i .and. zenith_angle > 90._r8 ) then
    1246           0 :                 sm = -1._r8
    1247             :              end if
    1248           0 :              rj   = re + zd(j-1)
    1249           0 :              rjp1 = re + zd(j)
    1250           0 :              dhj  = zd(j-1) - zd(j)
    1251           0 :              ga   = max( rj*rj - rpsinz*rpsinz,0._r8 )
    1252           0 :              gb   = max( rjp1*rjp1 - rpsinz*rpsinz,0._r8 )
    1253           0 :              if( id > i .and. j == id ) then
    1254           0 :                 dsj = sqrt( ga )
    1255             :              else
    1256           0 :                 dsj = sqrt( ga ) - sm*sqrt( gb )
    1257             :              end if
    1258           0 :              dsdh(i,j) = dsj / dhj
    1259             :            end do
    1260           0 :            nid(i) = id
    1261             :         else
    1262           0 :            nid(i) = -1
    1263             :         end if
    1264             :       end do
    1265             : 
    1266           0 :       end subroutine sphers
    1267             : 
    1268           0 :       subroutine slant_col( nlev, delz, dsdh, nid, absden, scol )
    1269             : !=============================================================================!
    1270             : !   PURPOSE:                                                                  !
    1271             : !   Derive Column
    1272             : !=============================================================================!
    1273             : !   PARAMETERS:                                                               !
    1274             : !   NLEV   - INTEGER, number of specified altitude levels in the working  (I) !
    1275             : !            grid                                                             !
    1276             : !   DELZ   - REAL, specified altitude working grid (km)                   (I) !
    1277             : !   DSDH   - REAL, slant path of direct beam through each layer crossed  (O)  !
    1278             : !             when travelling from the top of the atmosphere to layer i;      !
    1279             : !             DSDH(i,j), i = 0..NZ-1, j = 1..NZ-1                             !
    1280             : !   NID    - INTEGER, number of layers crossed by the direct beam when   (O)  !
    1281             : !             travelling from the top of the atmosphere to layer i;           !
    1282             : !             NID(i), i = 0..NZ-1                                             !
    1283             : !            specified altitude at each specified wavelength                  !
    1284             : !   absden - REAL, absorber concentration, molecules cm-3                     !
    1285             : !   SCOL   - REAL, absorber Slant Column, molecules cm-2                      !
    1286             : !=============================================================================!
    1287             : !   EDIT HISTORY:                                                             !
    1288             : !   09/01  Read in profile from an input file, DEK                            !
    1289             : !   01/02  Taken from Sasha Madronich's TUV code                              !
    1290             : !=============================================================================!
    1291             : 
    1292             :       implicit none
    1293             : 
    1294             : !------------------------------------------------------------------------------
    1295             : !       ... Dummy arguments
    1296             : !------------------------------------------------------------------------------
    1297             :       integer, intent(in) :: nlev
    1298             :       integer, intent(in) :: nid(0:nlev)                ! see above
    1299             :       real(r8), intent(in)    :: delz(nlev)             ! layer thickness (cm)
    1300             :       real(r8), intent(in)    :: dsdh(0:nlev,nlev)      ! see above
    1301             :       real(r8), intent(in)    :: absden(nlev)           ! absorber concentration (molec. cm-3)
    1302             :       real(r8), intent(out)   :: scol(nlev)             ! absorber Slant Column (molec. cm-2)
    1303             : 
    1304             : !------------------------------------------------------------------------------
    1305             : !       ... Local variables
    1306             : !------------------------------------------------------------------------------
    1307             :       real(r8), parameter :: largest = 1.e+36_r8
    1308             : 
    1309             :       real(r8) :: sum
    1310             :       real(r8) :: hscale
    1311             :       real(r8) :: numer, denom
    1312           0 :       real(r8) :: cz(nlev)
    1313             : 
    1314             :       integer :: id
    1315             :       integer :: j
    1316             :       integer :: k
    1317             : 
    1318             : !------------------------------------------------------------------------------
    1319             : !     ... compute column increments (logarithmic integrals)
    1320             : !------------------------------------------------------------------------------
    1321           0 :       do k = 1,nlev-1
    1322           0 :         if( absden(k) /= 0._r8 .and. absden(k+1) /= 0._r8 ) then
    1323           0 :            cz(nlev-k) = (absden(k) - absden(k+1))/log( absden(k)/absden(k+1) ) * delz(k)
    1324             :         else
    1325           0 :            cz(nlev-k) = .5_r8*(absden(k) + absden(k+1)) * delz(k)
    1326             :         end if
    1327             :       end do
    1328             : 
    1329             : !------------------------------------------------------------------------------
    1330             : !     ... Include exponential tail integral from infinity to model top
    1331             : !         specify scale height near top of data.For WACCM-X model, scale
    1332             : !         height needs to be increased for higher model top
    1333             : !------------------------------------------------------------------------------
    1334           0 :       if (nlev==pver) then
    1335           0 :          if ( waccmx_is('ionosphere') .or. waccmx_is('neutral') ) then
    1336             :            hscale     = 20.e5_r8
    1337             :          else
    1338           0 :            hscale     = 10.e5_r8
    1339             :          endif
    1340           0 :          cz(nlev-1) = cz(nlev-1) + hscale * absden(1)
    1341             :       endif
    1342             : 
    1343             : !------------------------------------------------------------------------------
    1344             : !       ...  Calculate vertical and slant column from each level:
    1345             : !            work downward
    1346             : !------------------------------------------------------------------------------
    1347           0 :       do id = 0,nlev-1
    1348           0 :          sum = 0._r8
    1349           0 :          if( nid(id) >= 0 ) then
    1350             : !------------------------------------------------------------------------------
    1351             : !       ...  Single pass layers:
    1352             : !------------------------------------------------------------------------------
    1353           0 :             do j = 1, min(nid(id), id)
    1354           0 :                sum = sum + cz(nlev-j)*dsdh(id,j)
    1355             :             end do
    1356             : !------------------------------------------------------------------------------
    1357             : !       ...  Double pass layers:
    1358             : !------------------------------------------------------------------------------
    1359           0 :             do j = min(nid(id),id)+1, nid(id)
    1360           0 :                sum = sum + 2._r8*cz(nlev-j)*dsdh(id,j)
    1361             :             end do
    1362             :          else
    1363             :             sum = largest
    1364             :          end if
    1365           0 :          scol(nlev-id) = sum
    1366             :       end do
    1367           0 :       scol(nlev) = .95_r8*scol(nlev-1)
    1368             : 
    1369           0 :       end subroutine slant_col
    1370             : 
    1371           0 :       subroutine lymana( nlev, o2scol, rm, ro2 )
    1372             : !-----------------------------------------------------------------------------!
    1373             : !   PURPOSE:                                                                  !
    1374             : !   Calculate the effective absorption cross section of O2 in the Lyman-Alpha !
    1375             : !   bands and an effective O2 optical depth at all altitudes.  Parameterized  !
    1376             : !   after:  Chabrillat, S., and G. Kockarts, Simple parameterization of the   !
    1377             : !   absorption of the solar Lyman-Alpha line, Geophysical Research Letters,   !
    1378             : !   Vol.24, No.21, pp 2659-2662, 1997. doi:10.1029/97GL52690 (note there is a !
    1379             : !   correction to this paper - the table was missing minuses in the exponents)!
    1380             : !-----------------------------------------------------------------------------!
    1381             : !   PARAMETERS:                                                               !
    1382             : !   nz      - INTEGER, number of specified altitude levels in the working (I) !
    1383             : !             grid                                                            !
    1384             : !   o2scol  - REAL, slant overhead O2 column (molec/cc) at each specified (I) !
    1385             : !             altitude                                                        !
    1386             : !   dto2la  - REAL, optical depth due to O2 absorption at each specified  (O) !
    1387             : !             vertical layer                                                  !
    1388             : !   xso2la  - REAL, molecular absorption cross section in LA bands        (O) !
    1389             : !-----------------------------------------------------------------------------!
    1390             : !   EDIT HISTORY:                                                             !
    1391             : !   01/15/2002 Taken from Sasha Madronich's TUV Version 4.1a, Doug Kinnison   !
    1392             : !   01/15/2002 Upgraded to F90, DK                                            !
    1393             : !-----------------------------------------------------------------------------!
    1394             : 
    1395             :       implicit none
    1396             : 
    1397             : !------------------------------------------------------------------------------
    1398             : !       ... Dummy arguments
    1399             : !------------------------------------------------------------------------------
    1400             :       integer, intent(in) :: nlev
    1401             :       real(r8), intent(in)    :: o2scol(nlev)
    1402             :       real(r8), intent(out)   :: ro2(nlev)
    1403             :       real(r8), intent(out)   :: rm(nlev)
    1404             : 
    1405             : !------------------------------------------------------------------------------
    1406             : !     ... Local variables
    1407             : !------------------------------------------------------------------------------
    1408             :       real(r8),save :: b(3)
    1409             :       real(r8),save :: c(3)
    1410             :       real(r8),save :: d(3)
    1411             :       real(r8),save :: e(3)
    1412             : 
    1413             :       data b / 6.8431e-01_r8, 2.29841e-01_r8,  8.65412e-02_r8 /, &
    1414             :            c / 8.22114e-21_r8, 1.77556e-20_r8,  8.22112e-21_r8 /, &
    1415             :            d / 6.0073e-21_r8, 4.28569e-21_r8,  1.28059e-20_r8 /, &
    1416             :            e / 8.21666e-21_r8, 1.63296e-20_r8,  4.85121e-17_r8 /
    1417             : 
    1418             :       integer  :: i, k
    1419             :       real(r8) :: wrk, term
    1420             : 
    1421             : !------------------------------------------------------------------------------
    1422             : !     ... Calculate reduction factors at every altitude
    1423             : !------------------------------------------------------------------------------
    1424           0 :       do k = 1,nlev
    1425             :          wrk = 0._r8
    1426           0 :          do i = 1,2 ! pc Dan Marsh
    1427           0 :             term = e(i)*o2scol(k)
    1428           0 :             if( term < 100._r8 ) then
    1429           0 :                wrk = wrk + d(i) * exp( -term )
    1430             :             end if
    1431             :          end do
    1432           0 :          ro2(k) = wrk
    1433           0 :          wrk = 0._r8
    1434           0 :          do i = 1,3
    1435           0 :             term = c(i)*o2scol(k)
    1436           0 :             if( term < 100._r8 ) then
    1437           0 :                wrk = wrk + b(i) * exp( -term )
    1438             :             end if
    1439             :          end do
    1440           0 :          rm(k) = wrk
    1441             :       end do
    1442             : 
    1443           0 :       end subroutine lymana
    1444             : 
    1445           0 :       subroutine calc_o2srb( nlev, nid, o2col, tlev, tsrb, xscho2 )
    1446             : !-----------------------------------------------------------------------------!
    1447             : !   PURPOSE:                                                                  !
    1448             : !   Calculate the equivalent absorption cross section of O2 in the SR bands.  !
    1449             : !   The algorithm is based on parameterization of G.A. Koppers, and           !
    1450             : !   D.P. Murtagh [ref. Ann.Geophys., 14 68-79, 1996]                          !
    1451             : !   Final values do include effects from the Herzberg continuum.              !
    1452             : !-----------------------------------------------------------------------------!
    1453             : !   PARAMETERS:                                                               !
    1454             : !   NZ      - INTEGER, number of specified altitude levels in the working (I) !
    1455             : !             grid                                                            !
    1456             : !   O2COL   - REAL, slant overhead O2 column (molec/cc) at each specified (I) !
    1457             : !             altitude                                                        !
    1458             : !   TLEV    - tmeperature at each level                                   (I) !
    1459             : !   TSRB    - REAL, transmission for the SRB                                  !
    1460             : !   XSCHO2  - REAL, molecular absorption cross section in SR bands at     (O) !
    1461             : !             each specified wavelength.  Includes Herzberg continuum         !
    1462             : !-----------------------------------------------------------------------------!
    1463             : !   EDIT HISTORY: Taken from TUV, 1/17/2002                                   !
    1464             : !   This code was supplied to TUV by Dan Marsh.                               !
    1465             : !-----------------------------------------------------------------------------!
    1466             : 
    1467             :       implicit none
    1468             : 
    1469             : !------------------------------------------------------------------------------
    1470             : !       ... Dummy arguments
    1471             : !------------------------------------------------------------------------------
    1472             :       integer, intent(in)     :: nlev
    1473             :       integer, intent(in)     :: nid(0:nlev)
    1474             :       real(r8), intent (in)   :: o2col(nlev)
    1475             :       real(r8), intent (in)   :: tlev(nlev)
    1476             :       real(r8), intent (out)  :: tsrb(nlev,nsrbtuv)
    1477             :       real(r8), intent (out)  :: xscho2(nlev,nsrbtuv)
    1478             : 
    1479             : !------------------------------------------------------------------------------
    1480             : !     ... Local variables
    1481             : !------------------------------------------------------------------------------
    1482             :       integer     :: i, k, ktop, ktop1, kbot
    1483             :       real(r8)    :: x, dto2
    1484             :       real(r8)    :: den, num
    1485             :       real(r8)    :: term1, term2
    1486           0 :       real(r8)    :: dtsrb(nlev)
    1487             :       real(r8)    :: tsrb_rev(nlev,nsrbtuv)
    1488             :       real(r8)    :: xs(nsrbtuv)
    1489             : 
    1490             : !------------------------------------------------------------------------------
    1491             : !     ... Calculate cross sections
    1492             : !------------------------------------------------------------------------------
    1493           0 :       ktop = nlev
    1494           0 :       kbot = 0
    1495             : 
    1496           0 :       do k = 1,nlev
    1497           0 :         x  = log( o2col(k) )
    1498           0 :         if( x >= lno2_llimit .and. x <= lno2_ulimit ) then
    1499             :           call effxs( x, tlev(k), xs )
    1500           0 :           xscho2(k,:) = xs(:)
    1501           0 :         else if( x < lno2_llimit ) then
    1502           0 :            ktop1 = k-1
    1503           0 :            ktop  = min( ktop1,ktop )
    1504           0 :         else if( x > lno2_ulimit ) then
    1505           0 :            kbot = k
    1506             :         end if
    1507             :       end do
    1508             : 
    1509           0 :       if ( kbot == nlev ) then
    1510           0 :          tsrb(:,:) = 0._r8
    1511           0 :          xscho2(:,:) = 0._r8
    1512             :          return
    1513             :       endif
    1514             : !------------------------------------------------------
    1515             : !     ... Fill in cross section where X is out of range
    1516             : !         by repeating edge table values
    1517             : !-------------------------------------------------------
    1518           0 :       if ( waccmx_is('ionosphere') .or. waccmx_is('neutral') ) then
    1519             : 
    1520             :          ! Need to be careful with nlev values for kbot and ktop.
    1521             :          ! This was handled by Hanli Liu fix.
    1522           0 :          if ( kbot < nlev ) then
    1523           0 :             do k = 1,kbot
    1524           0 :                xscho2(k,:) = xscho2(kbot+1,:)
    1525             :             end do
    1526           0 :             if (ktop < nlev) then
    1527           0 :                do k = ktop+1,nlev
    1528           0 :                   xscho2(k,:) = xscho2(ktop,:)
    1529             :                end do
    1530             :             else
    1531           0 :                xscho2(nlev,:) = 2.0e-19_r8
    1532             :             endif
    1533             :          else
    1534           0 :             do k = 1,kbot
    1535           0 :                xscho2(k,:) = 2.0e-19_r8
    1536             :             enddo
    1537             :          endif
    1538             : 
    1539             :       else
    1540           0 :          do k = 1,kbot
    1541           0 :             xscho2(k,:) = xscho2(kbot+1,:)
    1542             :          end do
    1543           0 :          do k = ktop+1,nlev
    1544           0 :             xscho2(k,:) = xscho2(ktop,:)
    1545             :          end do
    1546             :       endif
    1547             : 
    1548             : !-------------------------------------------------------
    1549             : !     ... Calculate incremental optical depths
    1550             : !-------------------------------------------------------
    1551           0 :       do i = 1,nsrbtuv
    1552           0 :         do k = 1,nlev-1
    1553           0 :            if( nid(nlev-k) /= -1 ) then
    1554             : !-------------------------------------------------------
    1555             : !     ... Calculate an optical depth weighted by density
    1556             : !-------------------------------------------------------
    1557           0 :                num   = xscho2(k+1,i)*o2col(k+1) - xscho2(k,i)*o2col(k)
    1558           0 :                if( num == 0._r8 ) then
    1559           0 :                   write(iulog,*) 'calc_o2srb : o2col(k:k+1),xscho2(k:k+1,i) = ',o2col(k:k+1),xscho2(k:k+1,i),' @ i,k = ',i,k
    1560             :                end if
    1561           0 :                term1 = log( xscho2(k+1,i)/xscho2(k,i) )
    1562           0 :                term2 = log( o2col(k+1)/o2col(k) )
    1563           0 :                if( term2 == 0._r8 ) then
    1564           0 :                   write(iulog,*) 'calc_o2srb : o2col(k:k+1),xscho2(k:k+1,i) = ',o2col(k:k+1),xscho2(k:k+1,i),' @ i,k = ',i,k
    1565           0 :                   call endrun
    1566             :                end if
    1567           0 :                den = 1._r8 + log( xscho2(k+1,i)/xscho2(k,i) )/log( o2col(k+1)/o2col(k) )
    1568           0 :                dto2 = abs(num/den)
    1569           0 :                if( dto2  < 100._r8 ) then
    1570           0 :                   dtsrb(k) = exp( -dto2 )
    1571             :                else
    1572           0 :                   dtsrb(k) = 0._r8
    1573             :                end if
    1574             :           else
    1575           0 :             dtsrb(k) = 0._r8
    1576             :           end if
    1577             :         end do
    1578             : !-----------------------------------------------
    1579             : !     ... Calculate Transmission for SRB
    1580             : !-----------------------------------------------
    1581           0 :         if (nlev==pver) then  ! waccm
    1582           0 :            tsrb(nlev,i) = 1._r8
    1583           0 :            do k = nlev-1,1,-1
    1584           0 :               tsrb(k,i) = tsrb(k+1,i)*dtsrb(k)
    1585             :            end do
    1586             :         else   ! cam-chem
    1587           0 :            tsrb(nlev,i) = exp(-xscho2(nlev,i)*o2col(nlev))
    1588           0 :            do k = nlev-1,1,-1
    1589           0 :               tsrb(k,i) = tsrb(k+1,i)*dtsrb(k)
    1590             :            end do
    1591             :         endif
    1592             : 
    1593             :       end do
    1594             : 
    1595             :       end subroutine calc_o2srb
    1596             : 
    1597           0 :       subroutine effxs( x, t, xs )
    1598             : !-------------------------------------------------------------
    1599             : !     Subroutine for evaluating the effective cross section
    1600             : !     of O2 in the Schumann-Runge bands using parameterization
    1601             : !     of G.A. Koppers, and D.P. Murtagh [ref. Ann.Geophys., 14
    1602             : !     68-79, 1996]
    1603             : !
    1604             : !     method:
    1605             : !     ln(xs) = A(X)[T-220]+B(X)
    1606             : !     X = log of slant column of O2
    1607             : !     A,B are calculated from Chebyshev polynomial coeffs
    1608             : !     AC and BC using Clenshaw summation algorithm within
    1609             : !     the interval 38<ln(NO2)<56.
    1610             : !
    1611             : !     Revision History:
    1612             : !
    1613             : !     drm 2/97  initial coding
    1614             : !-------------------------------------------------------------
    1615             : 
    1616             :       implicit none
    1617             : 
    1618             : !-------------------------------------------------------------
    1619             : !       ... Dummy arguments
    1620             : !-------------------------------------------------------------
    1621             :       real(r8), intent(in)  :: x
    1622             :       real(r8), intent(in)  :: t
    1623             :       real(r8), intent(out) :: xs(nsrbtuv)
    1624             : 
    1625             : !-------------------------------------------------------------
    1626             : !       ... Local variables
    1627             : !-------------------------------------------------------------
    1628             :       real(r8)  :: a(nsrbtuv), b(nsrbtuv)
    1629             : 
    1630           0 :       call calc_params( x, a, b )
    1631             : 
    1632           0 :       xs(:) = exp( a(:)*(t - 220._r8) + b(:) )
    1633             : 
    1634           0 :       end subroutine effxs
    1635             : 
    1636             : 
    1637           0 :       subroutine calc_params( x, a, b )
    1638             : !-------------------------------------------------------------
    1639             : !       calculates coefficients (A,B), used in calculating the
    1640             : !       effective cross section, for 17 wavelength intervals
    1641             : !       as a function of log O2 column density (X)
    1642             : !       Wavelength intervals are defined in WMO1985
    1643             : !-------------------------------------------------------------
    1644             : 
    1645             : !-------------------------------------------------------------
    1646             : !       ... Dummy arguments
    1647             : !-------------------------------------------------------------
    1648             :       real(r8), intent(in)  :: x
    1649             :       real(r8), intent(out) :: a(nsrbtuv), b(nsrbtuv)
    1650             : 
    1651             : !-------------------------------------------------------------
    1652             : !       ... Local variables
    1653             : !-------------------------------------------------------------
    1654             :       integer :: i
    1655             : 
    1656           0 :       if (x<lno2_llimit .or. x>lno2_ulimit) then
    1657           0 :          call endrun('mo_jshort::calc_params of O2 abs xs: x is not in the valid range. ')
    1658             :       end if
    1659             : 
    1660             : !-------------------------------------------------------------
    1661             : !     ... evaluate at each wavelength
    1662             : !         for a set of 20 Chebyshev coeficients
    1663             : !-------------------------------------------------------------
    1664           0 :       do i = 1,nsrbtuv
    1665           0 :          a(i) = evalchebpoly( ac(:,i), x )
    1666           0 :          b(i) = evalchebpoly( bc(:,i), x )
    1667             :       end do
    1668             : 
    1669             :       contains
    1670             : 
    1671             :         ! Use Clenshaw summation algorithm to evaluate Chebyshev polynomial at point
    1672             :         ! [pnt - (lno2_ulimit + lno2_llimit)/2]/[(lno2_ulimit - lno2_llimit)/2]
    1673             :         ! given coefficients coefs within limits lim1 and lim2
    1674           0 :         pure function evalchebpoly( coefs, pnt ) result(cval)
    1675             :           real(r8), intent(in) :: coefs(:)
    1676             :           real(r8), intent(in) :: pnt
    1677             : 
    1678             :           real(r8) :: cval
    1679             :           real(r8) :: fac(2)
    1680             :           real(r8) :: csum(2) ! Clenshaw summation
    1681             :           integer :: ndx
    1682             :           integer :: ncoef
    1683             : 
    1684           0 :           ncoef = size(coefs)
    1685             : 
    1686           0 :           fac(1) = (2._r8*pnt-lno2_llimit-lno2_ulimit)/(lno2_ulimit-lno2_llimit)
    1687           0 :           fac(2) = 2._r8*fac(1)
    1688             : 
    1689             :           ! Clenshaw recurrence summation
    1690           0 :           csum(:) = 0.0_r8
    1691           0 :           do ndx = ncoef, 2, -1
    1692           0 :              cval = csum(1)
    1693           0 :              csum(1) = fac(2)*csum(1) - csum(2) + coefs(ndx)
    1694           0 :              csum(2) = cval
    1695             :           end do
    1696             : 
    1697           0 :           cval = fac(1)*csum(1) - csum(2) + 0.5_r8*coefs(1)
    1698             : 
    1699           0 :         end function evalchebpoly
    1700             : 
    1701             :       end subroutine calc_params
    1702             : 
    1703           0 :       subroutine calc_jno( nlev, etfphot_ms93, n2cc, o2scol, o3scol, &
    1704           0 :                            noscol, jno )
    1705             : !-----------------------------------------------------------------------------!
    1706             : !   PURPOSE:                                                                  !
    1707             : !   Compute the total photolytic rate constant for NO in the SR bands         !
    1708             : !     - following the approach of Minshwanner and Siskind, JGR,               !
    1709             : !       98, D11, 20401-20412, 1993.                                           !
    1710             : !                                                                             !
    1711             : !-----------------------------------------------------------------------------!
    1712             : !   PARAMETERS:                                                               !
    1713             : !   NZ           - INTEGER, number of specified altitude levels               !
    1714             : !                                                                             !
    1715             : !   etfphot_ms93 - Extraterrestrial Flux, within the MS 1993 Grid             !
    1716             : !                  units of photons cm-2 sec-1 nm-1                           !
    1717             : !   n2cc         - N2 conc (molecules cm-3)                                   !
    1718             : !   o3scol       - Ozone Slant Column (molecules cm-2)                        !
    1719             : !   o2scol       - Oxygen Slant Column (molecules cm-2)                       !
    1720             : !   noscol       - Nitric Oxide Slant Column(molecules cm-2)                  !
    1721             : !                                                                             !
    1722             : !   LOCAL VARIABLES:                                                          !
    1723             : !   tauo3        - Transmission factor in the Hartley Band of O3              !
    1724             : !   etfphot_ms93 - Solar Irr. on Minschwaner and Siskind 1993 (MS93) Grid     !
    1725             : !   xs_o3ms93    - O3 cross section on the MS93 Grid                          !
    1726             : !                                                                             !
    1727             : !   OUTPUT VARIABLES:                                                         !
    1728             : !   jno          - photolytic rate constant                                   !
    1729             : !                  each specified altitude                                    !
    1730             : !                                                                             !
    1731             : !-----------------------------------------------------------------------------!
    1732             : !   EDIT HISTORY:                                                             !
    1733             : !   08/01  Created, Doug Kinnison, NCAR, ACD                                  !
    1734             : !-----------------------------------------------------------------------------!
    1735             : 
    1736             :       implicit none
    1737             : 
    1738             : !------------------------------------------------------------------------------
    1739             : !       ... Dummy arguments
    1740             : !------------------------------------------------------------------------------
    1741             :       integer, intent(in) :: nlev
    1742             :       real(r8), intent(in)    :: etfphot_ms93(num_ms93tuv)
    1743             :       real(r8), intent(in)    :: n2cc(nlev)
    1744             :       real(r8), intent(in)    :: o3scol(nlev)
    1745             :       real(r8), intent(in)    :: o2scol(nlev)
    1746             :       real(r8), intent(in)    :: noscol(nlev)
    1747             :       real(r8), intent(out)   :: jno(nlev)
    1748             : 
    1749             : !------------------------------------------------------------------------------
    1750             : !       ... Local variables
    1751             : !------------------------------------------------------------------------------
    1752             :       integer     :: i, iw, lev
    1753             :       real(r8)    :: jno50
    1754             :       real(r8)    :: jno90
    1755             :       real(r8)    :: jno100
    1756           0 :       real(r8)    :: tauo3(nlev,num_ms93tuv)
    1757             : 
    1758             : !------------------------------------------------------------------------------
    1759             : !       ... O3 SRB Cross Sections from WMO 1985, interpolated onto MS, 1993 grid
    1760             : !------------------------------------------------------------------------------
    1761             :       real(r8), save :: xso3_ms93(num_ms93tuv) = (/ 7.3307600e-19_r8, 6.9660105E-19_r8, 5.9257699E-19_r8, 4.8372219E-19_r8 /)
    1762             : 
    1763             : !------------------------------------------------------------------------------
    1764             : !       ... delta wavelength of the MS, 1993 grid
    1765             : !------------------------------------------------------------------------------
    1766             :       real(r8), save :: wlintv_ms93(num_ms93tuv) = (/ 1.50_r8, 1.50_r8, 5.6_r8, 2.3_r8 /)
    1767             : 
    1768             : !------------------------------------------------------------------------------
    1769             : !       ... O2 SRB Cross Sections for the six ODF regions, MS, 1993
    1770             : !------------------------------------------------------------------------------
    1771             :       real(r8), save :: cs250(6)  = (/ 1.117e-23_r8, 2.447e-23_r8, 7.188e-23_r8, 3.042e-22_r8, 1.748e-21_r8, 1.112e-20_r8 /)
    1772             :       real(r8), save :: cs290(6)  = (/ 1.350e-22_r8, 2.991e-22_r8, 7.334e-22_r8, 3.074e-21_r8, 1.689e-20_r8, 1.658e-19_r8 /)
    1773             :       real(r8), save :: cs2100(6) = (/ 2.968e-22_r8, 5.831e-22_r8, 2.053e-21_r8, 8.192e-21_r8, 4.802e-20_r8, 2.655e-19_r8 /)
    1774             : 
    1775             : !------------------------------------------------------------------------------
    1776             : !     ... derive tauo3 for the three o2 srb
    1777             : !     ... iw = 1,2, and 4 are used below for jno
    1778             : !------------------------------------------------------------------------------
    1779           0 :       do iw = 1,num_ms93tuv
    1780           0 :          tauo3(:,iw) = exp( -xso3_ms93(iw)*o3scol(:) )
    1781             :       end do
    1782             : 
    1783             : !------------------------------------------------------------------------------
    1784             : !       ... Call PJNO Function to derive SR Band JNO contributions
    1785             : !         Called in order of wavelength interval (shortest firs)
    1786             : !------------------------------------------------------------------------------
    1787           0 :       do lev = 1,nlev
    1788           0 :          jno100   = pjno( 1, cs2100, wtno100, csno100 )
    1789           0 :          jno90    = pjno( 2, cs290,  wtno90,  csno90 )
    1790           0 :          jno50    = pjno( 4, cs250,  wtno50,  csno50 )
    1791           0 :          jno(lev) = jno50 + jno90 + jno100
    1792             :       end do
    1793             : 
    1794             :       contains
    1795             : 
    1796           0 :       function pjno( w, cso2, wtno, csno )
    1797             : !------------------------------------------------------------------------------
    1798             : !       ... uses xsec at center of g subinterval for o2
    1799             : !           uses mean values for no
    1800             : !------------------------------------------------------------------------------
    1801             :        implicit none
    1802             : 
    1803             : !------------------------------------------------------------------------------
    1804             : !       ... parameters
    1805             : !------------------------------------------------------------------------------
    1806             :       integer, parameter :: ngint = 6
    1807             :       integer, parameter :: nno = 2
    1808             : 
    1809             : !----------------------------------------------------------------
    1810             : !       ... Dummy arguments
    1811             : !----------------------------------------------------------------
    1812             :       integer, intent(in)     :: w
    1813             :       real(r8),    intent(in) :: cso2(ngint)
    1814             :       real(r8),    intent(in) :: csno(ngint,nno)
    1815             :       real(r8),    intent(in) :: wtno(ngint,nno)
    1816             : 
    1817             : !----------------------------------------------------------------
    1818             : !       ... Function declarations
    1819             : !----------------------------------------------------------------
    1820             :       real(r8) :: pjno
    1821             : 
    1822             : !----------------------------------------------------------------
    1823             : !       ... Local variables
    1824             : !----------------------------------------------------------------
    1825             :       integer  ::  jj, i, k
    1826             :       real(r8) :: tauno
    1827             :       real(r8) :: transno
    1828             :       real(r8) :: transo2
    1829             :       real(r8) :: tauo2
    1830             :       real(r8) :: jno
    1831             :       real(r8) :: jno1
    1832             : 
    1833             : !----------------------------------------------------------------
    1834             : !       ... derive the photolysis frequency for no within a given
    1835             : !         srb (i.e., 5-0, 9-0, 10-0)
    1836             : !----------------------------------------------------------------
    1837           0 :       jno = 0._r8
    1838           0 :       do k = 1,ngint
    1839           0 :          tauo2 = o2scol(lev) * cso2(k)
    1840           0 :          if( tauo2 < 50._r8 ) then
    1841           0 :             transo2 = exp( -tauo2 )
    1842             :          else
    1843             :             transo2 = 0._r8
    1844             :          end if
    1845           0 :          jno1 = 0._r8
    1846           0 :          do jj = 1,nno
    1847           0 :             tauno = noscol(lev)*csno(k,jj)
    1848           0 :             if( tauno < 50._r8 ) then
    1849           0 :                transno = exp( -tauno )
    1850             :             else
    1851             :                transno = 0._r8
    1852             :             end if
    1853           0 :             jno1 = jno1 + csno(k,jj) * wtno(k,jj) * transno
    1854             :          end do
    1855           0 :          jno = jno + jno1*transo2
    1856             :       end do
    1857             : 
    1858           0 :       pjno = wlintv_ms93(w)*etfphot_ms93(w)*tauo3(lev,w)*jno
    1859             : 
    1860             : !----------------------------------------------------------------
    1861             : !       ... correct for the predissociation of the deltq 1-0
    1862             : !         transition in the srb (5-0)
    1863             : !----------------------------------------------------------------
    1864           0 :       if( w == 4 ) then
    1865           0 :         pjno = 1.65e9_r8/(5.1e7_r8 + 1.65e9_r8 + (1.5e-9_r8*n2cc(nlev-lev+1)))*pjno
    1866             :       end if
    1867             : 
    1868           0 :       end function pjno
    1869             : 
    1870             :       end subroutine calc_jno
    1871             : 
    1872             :       end module mo_jshort

Generated by: LCOV version 1.14