!=============================================================================
!
! $Id: synspc_update.F90,v 1.8 2006/04/15 02:36:20 kouatch Exp $
!
! CODE DEVELOPER
!   John Tannahill, LLNL
!   jrt@llnl.gov
!
! FILE
!   synspc_update.F
!
! ROUTINES
!   Update_Synspc
!   Calc_Synoz
!   Calc_Nodoz
!
! HISTORY
!   * September 23, 2004 - Jules Kouatchou
!     In the routine Calc_Synoz, do not update the variable "const"
!     if "io3_num /= 0" for the combined strat/trop chemical mechanism.
!   * December 8, 2005 - Bigyani Das
!     Introduced the parameter oz_eq_synoz_opt for synoz sensitivity
!     test runs
!=============================================================================
!-----------------------------------------------------------------------------
!
! ROUTINE
!   Update_Synspc
!
! DESCRIPTION
!   This routine updates the synthetic species.
!
! ARGUMENTS
!   do_nodoz : do Nodoz?
!   latdeg   : latitude (deg)
!   press3e  : atmospheric pressure at the edge of each grid box (mb)
!   const    : species concentration, known at zone centers (mixing ratio)
!
!-----------------------------------------------------------------------------


      subroutine Update_Synspc  & 1,2
     &  (do_nodoz, latdeg, press3e, const, synoz_threshold, tdt, &
     &   mw, io3_num, isynoz_num, ihno3_num, &
     &   num_nox, num_noy, nox_map, noy_map, oz_eq_synoz_opt, &
     &   i1, i2, ju1, j2, k1, k2, ilo, ihi, julo, jhi, ju1_gl, j2_gl, &
     &   num_species)

      implicit none

!     ----------------------
!     Argument declarations.
!     ----------------------

      integer, intent(in   ) :: i1, i2, ju1, j2, k1, k2
      integer, intent(in   ) :: ilo, ihi, julo, jhi, ju1_gl, j2_gl
      integer, intent(in   ) :: num_species
      integer, intent(in   ) :: oz_eq_synoz_opt
      integer, intent(in   ) :: io3_num, isynoz_num, ihno3_num
      integer, intent(in   ) :: num_nox, num_noy
      integer, intent(in   ) :: nox_map(num_nox), noy_map(num_noy)
      real*8 , intent(in   ) :: synoz_threshold
      real*8 , intent(in   ) :: tdt
      real*8 , intent(in   ) :: mw(num_species)
      logical, intent(in   ) :: do_nodoz
      real*8 , intent(in   ) :: latdeg (ju1_gl:j2_gl)
      real*8 , intent(in   ) :: press3e(ilo:ihi, julo:jhi, k1-1:k2)
      real*8 , intent(inout) :: const  (i1:i2, ju1:j2, k1:k2, num_species)

!     ----------------
!     Begin execution.
!     ----------------

!     ===============
      call Calc_Synoz  &
!     ===============
     &  (latdeg, press3e, const, tdt, oz_eq_synoz_opt, &
     &   mw, io3_num, isynoz_num, num_species, &
     &   i1, i2, ju1, j2, k1, k2, ilo, ihi, julo, jhi, ju1_gl, j2_gl)


      if (do_nodoz) then

!       ===============
        call Calc_Nodoz  &
!       ===============
     &    (latdeg, press3e, const, synoz_threshold, tdt,  &
     &   mw, ihno3_num, isynoz_num, num_nox, num_noy, nox_map, noy_map, &
     &   i1, i2, ju1, j2, k1, k2, ilo, ihi, julo, jhi, ju1_gl, j2_gl, num_species)

      end if

      return

      end


!-----------------------------------------------------------------------------
!
! ROUTINE
!   Calc_Synoz
!
! DESCRIPTION
!   This routine calculates Synoz emissions (mixing ratio/s) and removes
!   Synoz from the surface.
!
! ARGUMENTS
!   latdeg  : latitude (deg)
!   press3e : atmospheric pressure at the edge of each grid box (mb)
!   const   : species concentration, known at zone centers (mixing ratio)
!
!-----------------------------------------------------------------------------


      subroutine Calc_Synoz  & 1
     &  (latdeg, press3e, const, tdt, oz_eq_synoz_opt, &
     &   mw, io3_num, isynoz_num, num_species, &
     &   i1, i2, ju1, j2, k1, k2, ilo, ihi, julo, jhi, ju1_gl, j2_gl)

      implicit none

#     include "gmi_phys_constants.h"
#     include "gmi_time_constants.h"
#     include "gmi_chemcase.h"


!     ----------------------
!     Argument declarations.
!     ----------------------

      integer, intent(in   ) :: i1, i2, ju1, j2, k1, k2
      integer, intent(in   ) :: ilo, ihi, julo, jhi, ju1_gl, j2_gl
      integer, intent(in   ) :: num_species
      integer, intent(in   ) :: oz_eq_synoz_opt
      integer, intent(in   ) :: io3_num, isynoz_num
      real*8 , intent(in   ) :: mw(num_species)
      real*8 , intent(in   ) :: tdt
      real*8 , intent(in   ) :: latdeg (ju1_gl:j2_gl)
      real*8 , intent(in   ) :: press3e(ilo:ihi, julo:jhi, k1-1:k2)
      real*8 , intent(inout) :: const  (i1:i2, ju1:j2, k1:k2, num_species)

!     -----------------------
!     Parameter declarations.
!     -----------------------

      integer, parameter ::  &
     &  KSTX_REM = 1,  &
     &  KEND_REM = 2

      real*8, parameter  ::  &
     &  LOLAT = -30.0d0,  &
     &  HILAT =  30.0d0

      real*8, parameter  ::  &
     &  LOPRS =  10.0d0,  &
     &  HIPRS =  70.0d0

      real*8, parameter  ::  &
     &  SYNOZ_RELAX_DAYS =   2.0d0,  &
     &  SYNOZ_SRCFLUX    = 550.0d0,    & ! Synoz source flux (tg/yr)
     &  SYNOZ_SRFVAl     =   2.5d-8


!     ----------------------
!     Variable declarations.
!     ----------------------

      integer :: il, ij
      integer :: jsedge, jnedge
      integer :: kstx_emi, kend_emi

      logical, save :: doit     = .false.
      logical, save :: first    = .true.

      integer, save :: jstx_emi = -999
      integer, save :: jend_emi = -999

      real*8  :: rsecpdy, rsecpyr
      real*8  :: synoz_adjustment
      real*8  :: synoz_srcregion   ! relative size of Synoz source region to
                                   ! full atmosphere

      real*8, save :: synozadj_constant

      real*8  :: latdeg_edge(ju1_gl:j2_gl+1)  ! latitude at zone edge (deg)


!     ----------------
!     Begin execution.
!     ----------------

!     ==========
      if (first) then
!     ==========

        first = .false.

!       ---------------------------------------------------------
!       Determine latdeg_edge, but stay away from the Poles.
!       Synoz doesn't need latdeg_edge close to the Poles anyway.
!       latdeg_edge(ij) is the southern edge in latitude.
!       ---------------------------------------------------------

        latdeg_edge(ju1_gl)   = -90.0d0
        latdeg_edge(ju1_gl+1) = -90.0d0

        do ij = ju1_gl+2, j2_gl-1
          latdeg_edge(ij)     = (latdeg(ij-1) + latdeg(ij)) * 0.5d0
        end do

        latdeg_edge(j2_gl)    =  90.0d0
        latdeg_edge(j2_gl+1)  =  90.0d0


        if (Any ((latdeg_edge(ju1:j2)     >= LOLAT) .and.  &
     &           (latdeg_edge(ju1+1:j2+1) <= HILAT))) then

          doit = .true.

          jsedge   =  &
     &      Transfer  &
     &        (Minloc (latdeg_edge,  &
     &                 mask = (latdeg_edge >= LOLAT) .and.  &
     &                        (latdeg_edge <  HILAT)),  &
     &         1)

          jnedge   =  &
     &      Transfer  &
     &        (Maxloc (latdeg_edge,  &
     &                 mask = (latdeg_edge >  LOLAT) .and.  &
     &                        (latdeg_edge <= HILAT)),  &
     &         1)


          jstx_emi =  &
     &      Transfer  &
     &        (Minloc (latdeg_edge(ju1:j2),  &
     &                 mask = (latdeg_edge(ju1:j2)     >= LOLAT) .and.  &
     &                        (latdeg_edge(ju1+1:j2+1) <= HILAT)),  &
     &         1)

          jstx_emi = jstx_emi  + (ju1 - 1)


          jend_emi =  &
     &      Transfer  &
     &        (Maxloc (latdeg_edge(ju1:j2),  &
     &                 mask = (latdeg_edge(ju1:j2)     >= LOLAT) .and.  &
     &                        (latdeg_edge(ju1+1:j2+1) <= HILAT)),  &
     &         1)

          jend_emi = jend_emi + (ju1 - 1)


          synoz_srcregion =  &
     &      (Sin (latdeg_edge(jnedge) * RADPDEG) -  &
     &       Sin (latdeg_edge(jsedge) * RADPDEG)) *  &
     &      0.5d0 *  &
!c   &      ((HIPRS - LOPRS) / 993.407d0)
     &      ((HIPRS - LOPRS) / AVG_SRFPRS)


          rsecpyr = SECPYR

          synozadj_constant =  &
     &      tdt * SYNOZ_SRCFLUX *  &
     &      (MWTAIR / mw(isynoz_num)) /  &
     &      (rsecpyr * MASSATM * TGPKG * synoz_srcregion)

        end if

!     ======
      end if
!     ======


!     =========
      if (doit) then
!     =========

!       --------------------------
!       Calculate Synoz emissions.
!       --------------------------

        do ij = jstx_emi, jend_emi
          do il = i1, i2

            kstx_emi =  &
     &        Transfer  &
     &          (Maxloc (press3e(il,ij,k1:k2),  &
     &                   mask = (press3e(il,ij,0:k2-1) <= HIPRS) .and.  &
     &                          (press3e(il,ij,k1:k2)  >= LOPRS)),  &
     &           1)

            kstx_emi = kstx_emi + (k1 - 1)


            kend_emi =  &
     &        Transfer  &
     &          (Minloc (press3e(il,ij,k1:k2),  &
     &                   mask = (press3e(il,ij,0:k2-1) <= HIPRS) .and.  &
     &                          (press3e(il,ij,k1:k2)  >= LOPRS)),  &
     &           1)

            kend_emi = kend_emi + (k1 - 1)


            synoz_adjustment =  &
     &        synozadj_constant *  &
     &        ((HIPRS - LOPRS)  /  &
     &         (press3e(il,ij,kstx_emi-1) - press3e(il,ij,kend_emi)))


            const(il,ij,kstx_emi:kend_emi,isynoz_num) =  &
     &        const(il,ij,kstx_emi:kend_emi,isynoz_num) +  &
     &        synoz_adjustment

            IF (chem_mecha /= 'strat_trop' .or. oz_eq_synoz_opt /= 0) THEN
               if (io3_num /= 0) then
                 const(il,ij,kstx_emi:kend_emi,io3_num) =  &
     &             const(il,ij,kstx_emi:kend_emi,io3_num) +  &
     &             synoz_adjustment
               end if
            ENDIF

          end do
        end do

!     ======
      end if
!     ======


!     -----------------------------------
!     Calculate Synoz removal at surface.
!     -----------------------------------

      rsecpdy = SECPDY

      const(:,:,KSTX_REM:KEND_REM,isynoz_num) =  &
     &  SYNOZ_SRFVAL +  &
     &  Max ((const(:,:,KSTX_REM:KEND_REM,isynoz_num) - SYNOZ_SRFVAL),  &
     &       0.0d0) *  &
     &  Exp (-tdt / (SYNOZ_RELAX_DAYS * rsecpdy))


      return

      end


!-----------------------------------------------------------------------------
!
! ROUTINE
!   Calc_Nodoz
!
! DESCRIPTION
!   This routine calculates Nodoz emissions (mixing ratio/s) and
!   repartitions NOx and NOy above the troposphere.
!
! ARGUMENTS
!   latdeg  : latitude (deg)
!   press3e : atmospheric pressure at the edge of each grid box (mb)
!   const   : species concentration, known at zone centers (mixing ratio)
!
!-----------------------------------------------------------------------------


      subroutine Calc_Nodoz  & 1
     &  (latdeg, press3e, const, synoz_threshold, tdt,  &
     &   mw, ihno3_num, isynoz_num, num_nox, num_noy, nox_map, noy_map, &
     &   i1, i2, ju1, j2, k1, k2, ilo, ihi, julo, jhi, ju1_gl, j2_gl, num_species)

      implicit none

#     include "gmi_phys_constants.h"
#     include "gmi_time_constants.h"


!     ----------------------
!     Argument declarations.
!     ----------------------

      integer, intent(in   ) :: i1, i2, ju1, j2, k1, k2
      integer, intent(in   ) :: ilo, ihi, julo, jhi, ju1_gl, j2_gl
      integer, intent(in   ) :: num_species
      integer, intent(in   ) :: ihno3_num, isynoz_num
      integer, intent(in   ) :: num_nox, num_noy
      integer, intent(in   ) :: nox_map(num_nox), noy_map(num_noy)
      real*8 , intent(in   ) :: synoz_threshold
      real*8 , intent(in   ) :: tdt
      real*8 , intent(in   ) :: mw(num_species)
      real*8 , intent(in   ) :: latdeg (ju1_gl:j2_gl)
      real*8 , intent(in   ) :: press3e(ilo:ihi, julo:jhi, k1-1:k2)
      real*8 , intent(inout) :: const  (i1:i2, ju1:j2, k1:k2, num_species)


!     -----------------------
!     Parameter declarations.
!     -----------------------

      integer, parameter ::  &
     &  KEND_REM = 4,  &
     &  KSTX_REM = 1

      real*8, parameter ::  &
     &  HILAT =  30.0d0,  &
     &  LOLAT = -30.0d0

      real*8, parameter ::  &
     &  HIPRS  =  40.0d0,  &
     &  LOPRS  =   3.0d0,  &
     &  RLXPRS = 100.0d0

      real*8, parameter ::  &
     &  NODOZ_RELAX_DAYS = 3.0d0,  &
     &  NODOZ_SRCFLUX    = 2.295d0,    & ! Nodoz as HNO3 (tg/yr)
     &  NODOZ_SRFVAL     = 0.5d-9,  &
     &  RATIO            = 0.2d0,  &
     &  RATIO_RELAX_DAYS = 7.0d0


!     ----------------------
!     Variable declarations.
!     ----------------------

      logical, save :: doit  = .false.
      logical, save :: first = .true.

      integer :: il, ij, ic

!     --------------------------------------------------------------------
!     jnedge : global index of the northernmost latitude edge that lies on
!              or is south of HILAT; used to define the meridional extent
!              of the region of emission
!     jsedge : global index of the southernmost latitude edge that lies on
!              or is north of LOLAT; used to define the meridional extent
!              of the region of emission
!     --------------------------------------------------------------------

      integer :: jnedge, jsedge

!     -----------------------------------------------------------------
!     kend_emi : index of the highest (lowest pressure)  cell that lies
!                entirely between HIPRS and LOPRS
!     kstx_emi : index of the lowest  (highest pressure) cell that lies
!                entirely between HIPRS and LOPRS
!     -----------------------------------------------------------------

      integer :: kend_emi, kstx_emi

!     ----------------------------------------------------------------
!     kend_rlx : index in const of the highest (lowest pressure)  cell
!                with an upper edge below (higher pressure) RLXPRS
!     kstx_rlx : index in const of the lowest  (highest pressure) cell
!                with a Synoz value above SYNOZ_TROP (?)
!     ----------------------------------------------------------------

      integer :: kend_rlx, kstx_rlx

!     ------------------------------------------------------------------
!     jend_emi : index of the northernmost cell in the emission region
!     jstx_emi : index of the southernmost cell on the current processor
!                that is located entirely north of LOLAT
!     ------------------------------------------------------------------

      integer, save :: jstx_emi = -999
      integer, save :: jend_emi = -999

      real*8  :: nodoz_increment

!     --------------------------------------------------------------
!     nodoz_srcregion : relative size of Nodoz source region to full
!                       atmosphere
!     --------------------------------------------------------------

      real*8  :: nodoz_srcregion

      real*8  :: rsecpdy, rsecpyr

      real*8, save  :: nodoz_incconstant

!     -----------------------------------------
!     latdeg_edge : latitude at zone edge (deg)
!     -----------------------------------------

      real*8  :: latdeg_edge(ju1_gl:j2_gl+1)

      real*8  :: nox_adj  (k1:k2)
      real*8  :: nox_ratio(k1:k2)

      real*8  :: noy_adj  (k1:k2)

      real*8  :: sum_nox  (k1:k2)
      real*8  :: sum_noy  (k1:k2)


!     ----------------
!     Begin execution.
!     ----------------

!     ==========
      if (first) then
!     ==========

        first = .false.

!       ---------------------------------------------------------
!       Determine latdeg_edge, but stay away from the Poles.
!       Nodoz doesn't need latdeg_edge close to the Poles anyway.
!       latdeg_edge(ij) is the southern edge in latitude.
!       ---------------------------------------------------------

        latdeg_edge(ju1_gl)   = -90.0d0
        latdeg_edge(ju1_gl+1) = -90.0d0

        do ij = ju1_gl+2, j2_gl-1
          latdeg_edge(ij)     = (latdeg(ij-1) + latdeg(ij)) * 0.5d0
        end do

        latdeg_edge(j2_gl)    =  90.0d0
        latdeg_edge(j2_gl+1)  =  90.0d0


        if (Any ((latdeg_edge(ju1:j2)     >= LOLAT) .and.  &
     &           (latdeg_edge(ju1+1:j2+1) <= HILAT))) then

          doit = .true.

!         -----------------------------------------------------------------
!         The masks in the following two equations preselect only those
!         edges contained within LOLAT and HILAT.
!
!         Note that jsedge must be < jnedge for emission of Nodoz to occur.
!         -----------------------------------------------------------------

          jnedge =  &
     &      Transfer  &
     &        (Maxloc (latdeg_edge,  &
     &                 mask = (latdeg_edge >  LOLAT) .and.  &
     &                        (latdeg_edge <= HILAT)),  &
     &         1)

          jsedge =  &
     &      Transfer  &
     &        (Minloc (latdeg_edge,  &
     &                 mask = (latdeg_edge >= LOLAT) .and.  &
     &                        (latdeg_edge <  HILAT)),  &
     &         1)


!         -------------------------------------------------------------
!         The masks in the following two equations preselect only those
!         cells that are contained entirely within LOLAT and HILAT.
!         The result of the Minloc function is the smallest index,
!         counting from 1 in the subselected latdeg array, that
!         corresponds to a cell with a southern boundary lying on or
!         north of LOLAT and a northern boundary on or south of HILAT.
!         -------------------------------------------------------------

          jend_emi =  &
     &      Transfer  &
     &        (Maxloc (latdeg_edge(ju1:j2),  &
     &                 mask = (latdeg_edge(ju1:j2)     >= LOLAT) .and.  &
     &                        (latdeg_edge(ju1+1:j2+1) <= HILAT)),  &
     &         1)

          jstx_emi =  &
     &      Transfer  &
     &        (Minloc (latdeg_edge(ju1:j2),  &
     &                 mask = (latdeg_edge(ju1:j2)     >= LOLAT) .and.  &
     &                        (latdeg_edge(ju1+1:j2+1) <= HILAT)),  &
     &         1)

!         ------------------------------------------------------------
!         (ju1 - 1) below is the offset that must be added to jend_emi
!         and jstx_emi for indexing into the const array.
!         ------------------------------------------------------------

          jend_emi = jend_emi + (ju1 - 1)
          jstx_emi = jstx_emi + (ju1 - 1)


!         ------------------------------------------------------------
!         Note that AVG_SRFPRS below should be the true annual average
!         surface pressure for the global met field used.
!         ------------------------------------------------------------

          nodoz_srcregion =  &
     &      (Sin (latdeg_edge(jnedge) * RADPDEG) -  &
     &       Sin (latdeg_edge(jsedge) * RADPDEG)) *  &
     &      0.5d0 *  &
!c   &      ((HIPRS - LOPRS) / 993.407d0)
     &      ((HIPRS - LOPRS) / AVG_SRFPRS)


          rsecpyr = SECPYR

          nodoz_incconstant =  &
     &      tdt * NODOZ_SRCFLUX *  &
     &      (MWTAIR / mw(ihno3_num)) /  &
     &      (rsecpyr * MASSATM * TGPKG * nodoz_srcregion)

        end if

!     ======
      end if
!     ======


!     =========
      if (doit) then
!     =========

!       --------------------------
!       Calculate Nodoz emissions.
!       --------------------------

        do ij = jstx_emi, jend_emi
          do il = i1, i2

            kend_emi =  &
     &        Transfer  &
     &          (Minloc (press3e(il,ij,k1:k2),  &
     &                   mask = (press3e(il,ij,0:k2-1) <= HIPRS) .and.  &
     &                          (press3e(il,ij,k1:k2)  >= LOPRS)),  &
     &           1)

            kstx_emi =  &
     &        Transfer  &
     &          (Maxloc (press3e(il,ij,k1:k2),  &
     &                   mask = (press3e(il,ij,0:k2-1) <= HIPRS) .and.  &
     &                          (press3e(il,ij,k1:k2)  >= LOPRS)),  &
     &           1)

!           ----------------------------------------------------------
!           If, at some future time the parallel decomposition extends
!           to sending portions of the vertical column to different
!           processors, the k1 offset would need to be accounted for.
!           ----------------------------------------------------------

!c          kend_emi = kend_emi + (k1 - 1)
!c          kstx_emi = kstx_emi + (k1 - 1)


!           -----------------------------------------------------------
!           The high pressure edge index here (kstx_emi) is decremented
!           to account for the zero-based indexing of press3e.
!           -----------------------------------------------------------

            nodoz_increment =  &
     &        nodoz_incconstant *  &
     &        ((HIPRS - LOPRS)  /  &
     &         (press3e(il,ij,kstx_emi-1) - press3e(il,ij,kend_emi)))


!           -------------------------------
!           Actual Nodoz emission operator.
!           -------------------------------

            const(il,ij,kstx_emi:kend_emi,ihno3_num) =  &
     &        const(il,ij,kstx_emi:kend_emi,ihno3_num) +  &
     &        nodoz_increment

          end do
        end do

!     ======
      end if
!     ======

      if ((num_nox == 0) .and. (num_noy == 0)) then

!     -----------------------------------
!     Calculate Nodoz removal at surface.
!     -----------------------------------

      rsecpdy = SECPDY

      const(:,:,KSTX_REM:KEND_REM,ihno3_num) =  &
     &  NODOZ_SRFVAL +  &
     &  Max ((const(:,:,KSTX_REM:KEND_REM,ihno3_num) - NODOZ_SRFVAL),  &
     &       0.0d0) *  &
     &  Exp (-tdt / (NODOZ_RELAX_DAYS * rsecpdy))



      else

!     --------------------------
!     Calculate NOy partitioning.
!     --------------------------

      do ij = ju1, j2
        do il = i1, i2

          kend_rlx =  &
     &      Transfer  &
     &        (Minloc (press3e(il,ij,k1:k2),  &
     &                 mask = (press3e(il,ij,k1:k2) >= RLXPRS)),  &
     &         1)

          kstx_rlx =  &
     &      Transfer  &
     &        (Maxloc (press3e(il,ij,k1:k2),  &
     &                 mask = (const(il,ij,k1:k2,isynoz_num) >  &
     &                         synoz_threshold)),  &
     &         1)

!         ----------------------------------------------------------
!         If, at some future time the parallel decomposition extends
!         to sending portions of the vertical column to different
!         processors, the k1 offset would need to be accounted for.
!         ----------------------------------------------------------

!c        kend_rlx = kend_rlx + (k1 - 1)
!c        kstx_rlx = kstx_rlx + (k1 - 1)


!         ------------------------------------
!         Assemble NOx and NOy sums and ratio.
!         ------------------------------------

          sum_nox(:) = 0.0d0

          do ic = 1, num_nox

            sum_nox = sum_nox +  &
     &                const(il,ij,:,nox_map(ic))

          end do

          sum_noy(:) = sum_nox(:)

          do ic = 1, num_noy

            sum_noy = sum_noy +  &
     &                const(il,ij,:,noy_map(ic))

          end do

          nox_ratio(:) = sum_nox(:) / sum_noy(:)


!         ----------------------------------------------------------
!         Between the Synoz tropopause and RLXPRS, relax the NOx/NOy
!         ratio to the imposed RATIO with a RATIO_RELAX_DAYS
!         relaxation time constant.
!         ----------------------------------------------------------

          rsecpdy    = SECPDY

          nox_adj(:) = 1.0d0

          if (kend_rlx >= kstx_rlx) then

            nox_adj(kstx_rlx:kend_rlx) =  &
     &        (RATIO +  &
     &         (nox_ratio(kstx_rlx:kend_rlx) - RATIO) *  &
     &         Exp(-tdt / (RATIO_RELAX_DAYS * rsecpdy))) /  &
     &        nox_ratio(kstx_rlx:kend_rlx)

          end if


!         --------------------------------------------------
!         Above RLXPRS (at lower pressures), force NOx / NOy
!         ratio, retaining subgroup partitioning.
!         --------------------------------------------------

          nox_adj(kend_rlx+1:k2) = RATIO / nox_ratio(kend_rlx+1:k2)


!         ------------------
!         Adjust NOx values.
!         ------------------

          do ic = 1, num_nox

            const(il,ij,kstx_rlx:k2,nox_map(ic)) =  &
     &        nox_adj(kstx_rlx:k2) *  &
     &        const(il,ij,kstx_rlx:k2,nox_map(ic))

          end do


!         ------------------
!         Adjust NOy values.
!         ------------------

          noy_adj(:) = 1.0d0

          noy_adj(kstx_rlx:k2) =  &
     &      (1.0d0 - nox_adj  (kstx_rlx:k2) * nox_ratio(kstx_rlx:k2)) /  &
     &      (1.0d0 - nox_ratio(kstx_rlx:k2))

          do ic = 1, num_noy

            const(il,ij,kstx_rlx:k2,noy_map(ic)) =  &
     &        noy_adj(kstx_rlx:k2) *  &
     &        const(il,ij,kstx_rlx:k2,noy_map(ic))

          end do

        end do
      end do

      end if


      return

      end