!-------------------------------------- LICENCE BEGIN ------------------------------------
!Environment Canada - Atmospheric Science and Technology License/Disclaimer, 
!                     version 3; Last Modified: May 7, 2008.
!This is free but copyrighted software; you can use/redistribute/modify it under the terms 
!of the Environment Canada - Atmospheric Science and Technology License/Disclaimer 
!version 3 or (at your option) any later version that should be found at: 
!http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html 
!
!This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
!without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
!See the above mentioned License/Disclaimer for more details.
!You should have received a copy of the License/Disclaimer along with this software; 
!if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec), 
!CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca
!-------------------------------------- LICENCE END --------------------------------------
***s/r  bacp_2 - backsubstitution ( computation and microtasking )
*
#include "model_macros_f.h"
*

      subroutine bacp_2 ( F_itr , F_itnlh, F_st0  , F_pipt0, 2
     $                    F_qt0 , F_fit0 , F_fipt0, F_fis   , F_tt0  ,
     $                    F_tpt0, F_tplt0, F_ut0  , F_vt0   , F_psdt0,
     $                    F_tdt0, F_qpt0 , F_wt0  ,
     $                    F_mut0, F_multx, F_gptx , F_gxtx  , 
     $                    F_ru  , F_rv   , F_rth  , F_r3    , F_r3p  ,
     $                    F_rvv , F_rcn  , F_nu   , F_nv    ,
     $                    F_nth , F_n3   , F_n3p  , F_ncn,
     $                    F_wijk0,F_wijk1, DIST_DIM, Nk )
*
      implicit none
*
      integer  F_itr, F_itnlh, DIST_DIM, Nk 
      real     F_st0  (DIST_SHAPE)    ,
     %         F_pipt0(DIST_SHAPE,Nk) ,  F_qt0  (DIST_SHAPE,Nk) , 
     %         F_fit0 (DIST_SHAPE,Nk) ,  F_fipt0(DIST_SHAPE,Nk) , 
     %         F_fis  (DIST_SHAPE)    ,  F_tt0  (DIST_SHAPE,Nk) ,
     %         F_tpt0 (DIST_SHAPE,Nk) ,  F_tplt0(DIST_SHAPE,Nk) , 
     %         F_ut0  (DIST_SHAPE,Nk) ,  F_vt0  (DIST_SHAPE,Nk) , 
     %         F_psdt0(DIST_SHAPE,Nk) ,  F_tdt0 (DIST_SHAPE,Nk) , 
     %         F_qpt0 (DIST_SHAPE,Nk) ,  F_wt0  (DIST_SHAPE,Nk) , 
     %         F_mut0 (DIST_SHAPE,Nk) ,  F_multx(DIST_SHAPE,Nk) , 
     %         F_gptx (DIST_SHAPE,Nk) ,  F_gxtx (DIST_SHAPE,Nk) , 
     %         F_ru   (DIST_SHAPE,Nk) ,  F_rv   (DIST_SHAPE,Nk) , 
     %         F_rcn  (DIST_SHAPE,Nk) ,  F_rth  (DIST_SHAPE,Nk) , 
     %         F_rvv  (DIST_SHAPE,Nk) ,  F_nth  (DIST_SHAPE,Nk) , 
     %         F_r3   (DIST_SHAPE,Nk) ,  F_r3p  (DIST_SHAPE,Nk) , 
     %         F_nu   (DIST_SHAPE,Nk) ,  F_nv   (DIST_SHAPE,Nk) , 
     %         F_n3   (DIST_SHAPE,Nk) ,  F_n3p  (DIST_SHAPE,Nk) ,
     %         F_ncn  (DIST_SHAPE,Nk) ,
     %         F_wijk0(DIST_SHAPE,Nk) ,  F_wijk1(DIST_SHAPE,Nk)
*
*author
*     Alain Patoine - split from bac.ftn
*
*revision
* v2_00 - Desgagne M.       - initial MPI version (from rhs v1_03)
* v2_21 - Lee V.            - modifications for LAM version
* v2_30 - Edouard  S.       - adapt for vertical hybrid coordinate
* v2_31 - Desgagne M.       - removed treatment of Hu and Qc
* v3_00 - Desgagne & Lee    - Lam configuration
* v3_02 - Edouard S.        - correct non-hydrostatic version (F_mut0,F_tpt0,bbb3)
* v3_10 - Corbeil & Desgagne & Lee - AIXport+Opti+OpenMP
* v3_21 - Desgagne M.       - Revision Openmp
* v3_30 - Desgagne M.       - Revision Openmp II
*
*object
*     see documentation in s/r bac.
*
*arguments: see documentation of appropriate comdecks 
*
*implicits
#include "glb_ld.cdk"
#include "orh.cdk"
#include "cori.cdk"
#include "cstv.cdk"
#include "dcst.cdk"
#include "geomg.cdk"
#include "schm.cdk"
*
      integer i, j, k, i0, j0, in, jn, nij
      real*8  gamma, eps, aaa, bbb, ccc, ddd, a1, b1, b2, xxx, yyy , 
     $        zzz, pd2, aaa1, aaa2, bbb1, bbb2, bbb3, ccc1, ccc2, ddd1,
     $        tmp_8, c1_8, c2_8, c3_8, xlog_8(l_ni,l_nj),
     $        ylog_8(l_ni,l_nj), yexp_8(l_ni,l_nj),
     $        xrec_8(l_ni,l_nj), yrec_8(l_ni,l_nj)
      real*8 zero, one, two, half, quarter
      parameter( zero=0.0, one=1.0, two=2.0, half=.5, quarter=.25 )
**
*     __________________________________________________________________
*
!$omp parallel private( i, j, k, i0, j0, in, jn, nij,
!$omp%                  gamma, eps, aaa, bbb, ccc, ddd, a1, b1, b2, xxx,
!$omp%                  yyy, zzz, pd2, aaa1, aaa2, bbb1, bbb2, bbb3, 
!$omp%                  ccc1, ccc2, ddd1, tmp_8, c1_8, c2_8, c3_8,
!$omp%                  xlog_8, ylog_8, xrec_8, yrec_8 )
!$omp%         shared ( yexp_8 )
*
      i0 = 1+pil_w
      in = l_ni-pil_e
      j0 = 1+pil_s
      jn = l_nj-pil_n
*
*     Constants for nonhydro distortion 
*     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      gamma = one
      if (.not. Schm_hydro_L) then
           eps =  Schm_nonhy_8 * Dcst_rgasd_8   * Cstv_tstr_8
     %         /( Dcst_cappa_8 * Dcst_grav_8**2 * Cstv_tau_8**2 )
         gamma =  one/( one + eps )
      endif
*
      nij = l_ni * l_nj
*
      if ( (Cori_cornl_L) .or. (F_itr .lt. F_itnlh) ) then
!$omp single
         call rpn_comm_xch_halo( F_gptx, LDIST_DIM,l_ni,l_nj,G_nk,
     $                 G_halox,G_haloy,G_periodx,G_periody,l_ni,0)
!$omp end single
      endif
*
**********************************************************
*  1. Retrieve the nonhydro deviation q' of log pressure *
**********************************************************
*
      aaa  = gamma/( Dcst_cappa_8*Cstv_tau_8*Dcst_rgasd_8*Cstv_tstr_8 )
      aaa1 = Dcst_rgasd_8*Cstv_tstr_8
      aaa2 = one/Dcst_rayt_8**2  
      bbb  = Geomg_z_8(l_nk) / ( Dcst_rgasd_8*Cstv_tstr_8 )
      bbb1 = Dcst_cappa_8*Cstv_tstr_8
      bbb2 = one/(Dcst_grav_8*Cstv_tau_8)
      bbb3 = Schm_nonhy_8/((Dcst_grav_8**2)*(Cstv_tau_8**2)) 
      c1_8 = 1.0d0 / Dcst_cappa_8
      c2_8 = 1.0d0 / geomg_pib(l_nk)
      c3_8 = 1.0d0 / Dcst_grav_8
      ccc  = Schm_nonhy_8*gamma/( Dcst_grav_8**2 * Cstv_tau_8**3 )
      ccc1 = Geomg_z_8(l_nk) * c2_8
      ccc2 = Dcst_rgasd_8*Cstv_tstr_8 
      ddd  = Schm_nonhy_8 * gamma
     %      /( Dcst_cappa_8 * Dcst_grav_8**2 * Cstv_tau_8**3 )
      ddd1 = Cstv_tau_8*Cstv_tstr_8
*
      if (.not. Schm_hydro_L) then
*
!$omp do
         do j= j0, jn 
            F_qpt0(:,j,1) = zero
            do k=1,l_nk-1 
            xxx = half*Geomg_hz_8(k) 
            yyy = (ccc*c1_8)*half*( Geomg_z_8(k) + Geomg_z_8(k+1) )
            zzz = Cstv_tau_8*geomg_invz_8(k)
            do i= i0, in 
               F_qpt0(i,j,k+1) = F_qpt0(i,j,k) 
     %       + xxx*( gamma*(F_n3p(i,j,k+1)-F_r3p(i,j,k+1))
     %       + ccc*F_gptx(i,j,k+1) + gamma*(F_n3p(i,j,k)-F_r3p(i,j,k))
     %       + ccc*F_gptx(i,j,k) ) + yyy*(F_gptx(i,j,k+1)-F_gptx(i,j,k))
               F_qpt0(i,j,k) = zzz*F_qpt0(i,j,k)
            end do
            end do
            do i= i0, in 
            F_qpt0(i,j,l_nk) = 
     $            Cstv_tau_8*F_qpt0(i,j,l_nk)*geomg_invz_8(l_nk)
            end do
         end do
!$omp enddo 
*
      endif
*
******************************************
*  2. Compute s, pi'lin, pi', q and phi' *
******************************************
*
*     Compute s
*     ~~~~~~~~~
!$omp do
      do j= j0, jn 
      do i= i0, in 
        F_st0(i,j) = bbb*F_gptx(i,j,l_nk) * c2_8
      end do
      end do
!$omp enddo
*
      if (.not. Schm_hydro_L) then
!$omp do
         do j= j0, jn 
         do i= i0, in 
            F_st0(i,j) = F_st0(i,j) - ccc1*F_qpt0(i,j,l_nk) 
         end do
         end do
!$omp enddo
      endif 
*
*     Compute pi'lin (F_wijk0), pi', q and phi'
*     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
!$omp do
      do j= j0, jn
         yexp_8(:,j) = 1.
         do i= i0, in 
            yexp_8(i,j) = F_st0(i,j)
         end do
         call vexp ( yexp_8(1,j), yexp_8(1,j), l_ni )
      end do
!$omp enddo 
*
      xlog_8 = 1.
      xrec_8 = 1.
!$omp do
      do 100 k=1,l_nk 
*
         if (k.eq.1) then

*        Impose the boundary conditions 
*        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             do j= j0, jn 
             do i= i0, in 
                F_pipt0(i,j,1) = geomg_pib(1) * (yexp_8(i,j) - one)
                xlog_8(i,j)    = Geomg_z_8(1) + F_pipt0(i,j,1)
             end do
             end do
             call vlog ( ylog_8, xlog_8, nij )
*
             do j= j0, jn 
             do i= i0, in 
                F_qt0  (i,j,1) = ylog_8(i,j)
                F_fipt0(i,j,1) = F_gptx (i,j,1)
                F_gxtx (i,j,1) = 0. 
             end do
             end do
         else
             xxx = Geomg_z_8(k) - Geomg_z_8(1) 
             yyy = Dcst_rgasd_8*Cstv_tstr_8 * geomg_invz_8(k) 
             do j= j0, jn 
             do i= i0, in 
                F_pipt0(i,j,k)= geomg_pib(k) * (yexp_8(i,j) - one)
                xlog_8(i,j)   = Geomg_z_8(k) + F_pipt0(i,j,k)
             end do
             end do
             call vlog ( ylog_8, xlog_8, nij )
             do j= j0, jn 
             do i= i0, in 
                F_wijk0(i,j,k)= geomg_pib(k) * F_st0(i,j)
                F_qt0  (i,j,k)= ylog_8(i,j)
                F_fipt0(i,j,k)= F_gptx(i,j,k) - yyy*F_wijk0(i,j,k) 
             end do
             end do

             if (.not. Schm_hydro_L) then
                do j= j0, jn 
                do i= i0, in 
                   F_qt0  (i,j,k) =   F_qt0(i,j,k) +     F_qpt0(i,j,k) 
                   F_fipt0(i,j,k) = F_fipt0(i,j,k) - ccc2*F_qpt0(i,j,k) 
                end do
                end do
             endif 
         endif
         if (k.eq.l_nk) then
            F_fipt0 (:,:,l_nk) = zero 
         endif
*
*******************************
*  3. Retrieve the variable X * 
*******************************
*
*     Compute term {1} (F_wijk1) without vertical staggering 
*     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         xxx = gamma/Dcst_cappa_8*Geomg_z_8(k) 
         b1 = Geomg_z_8(k)/Cstv_tau_8 
         b2 = ddd*Geomg_z_8(k) 
         do j= j0, jn 
         do i= i0, in 
            F_wijk1(i,j,k) = xxx*(F_nth(i,j,k) - F_rth(i,j,k))
         end do
         end do
*
         if (.not. Schm_hydro_L) then
            do j= j0, jn 
            do i= i0, in 
               F_wijk1(i,j,k) = F_wijk1(i,j,k) +
     $                       xxx*( F_n3(i,j,k) - F_r3(i,j,k) )
     $                       -b1*F_qpt0(i,j,k) + b2*F_gptx(i,j,k)
            end do
            end do
         endif
*
 100  continue
!$omp enddo
*
!$omp do
      do j= j0, jn 
         do k=1,l_nk-1 
         a1=aaa*quarter*(Geomg_z_8(k)+Geomg_z_8(k+1))**2/Geomg_hz_8(k) 
         do i= i0, in 
            F_wijk1(i,j,k) = half*( F_wijk1(i,j,k+1) + F_wijk1(i,j,k) )
     %                      - a1*(  F_gptx (i,j,k+1) - F_gptx (i,j,k) )
         end do
         end do
*
*        Compute the desired variable X 
*        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         do k=1,l_nk-1 
         do i= i0, in 
            F_gxtx(i,j,k+1) = - F_gxtx(i,j,k) + two*F_wijk1(i,j,k) 
         end do
         end do
      end do
!$omp enddo
*
********************************************************
*  4. Compute vertical velocity & nonhydrostatic index * 
********************************************************
*
!$omp do
      do 300 k=1,l_nk 
*
         if (.not. Schm_hydro_L) then
            a1 = aaa1*Cstv_tau_8*geomg_invz_8(k) 
            do j= j0, jn 
            do i= i0, in 
               zzz =  1.0 / (1.0 + geomg_dpib(k)*(yexp_8(i,j) - 1.0))
               xxx = F_gptx(i,j,k)-aaa1*F_qpt0(i,j,k)-a1*F_gxtx(i,j,k)
               F_wt0  (i,j,k)= - F_rvv(i,j,k)*c3_8 + bbb2*xxx 
               F_multx(i,j,k)= Cstv_tau_8
     $                        *(F_n3(i,j,k)-F_r3(i,j,k))+bbb3*xxx 
               yyy = (1.+F_pipt0(i,j,k)*geomg_invz_8(k))*
     $                            (F_multx(i,j,k)-F_qpt0(i,j,k))
               F_mut0(i,j,k) = exp(F_qpt0(i,j,k))-1.
     $                        +exp(F_qpt0(i,j,k))*zzz*yyy
            end do
            end do
         endif

********************************************
*  5. Compute the temperature perturbation * 
********************************************
*     Compute T'lin and prepare {$} (F_wijk1) 
*     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         a1 = Dcst_cappa_8*geomg_invz_8(k) 
         do j= j0, jn 
         do i= i0, in 
            F_tplt0(i,j,k)= ddd1*(F_rth(i,j,k) - F_nth(i,j,k) + 
     $                      a1*F_gxtx(i,j,k))
         end do
         end do

         if (.not. Schm_hydro_L) then
             do j= j0, jn 
             do i= i0, in 
                F_tplt0(i,j,k) = F_tplt0(i,j,k) + bbb1*F_qpt0(i,j,k) 
             end do
             end do
         endif 
*
*     Compute T'
*     ~~~~~~~~~
         do j= j0, jn 
         do i= i0, in 
            xrec_8(i,j) = 1.0 + geomg_dpib(k) * (yexp_8(i,j) - 1.0)
         end do
         end do
         call vrec ( yrec_8, xrec_8, nij )
*
         if (Schm_hydro_L) then
         do j= j0, jn 
         do i= i0, in 
            xrec_8(i,j) = (1.+F_pipt0(i,j,k)*geomg_invz_8(k)) * yrec_8(i,j)
            yrec_8(i,j) = F_tplt0(i,j,k)-Cstv_tstr_8* ( F_st0(i,j)*(geomg_pib(k) * geomg_invz_8(k) - geomg_dpib(k))                 -1. )
         end do
         end do
         else
         do j= j0, jn 
         do i= i0, in 
            xrec_8(i,j) = (1.+F_pipt0(i,j,k)*geomg_invz_8(k)) * yrec_8(i,j) * exp(F_qpt0(i,j,k))
            yrec_8(i,j) = F_tplt0(i,j,k)-Cstv_tstr_8* ( F_st0(i,j)*(geomg_pib(k) * geomg_invz_8(k) - geomg_dpib(k)) + F_qpt0(i,j,k) -1. )
         end do
         end do
         endif
*
         do j= j0, jn 
         do i= i0, in 
            F_tpt0(i,j,k) = xrec_8(i,j)*yrec_8(i,j) - Cstv_tstr_8
         end do
         end do
*
 300  continue
!$omp enddo
*
      if (Cori_cornl_L) then
*
!$omp do
      do 600 k=1,l_nk
*
*     Compute gradient of P and hence U & V 
*     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         do j= j0, jn 
         do i= i0, l_niu-pil_e
            F_ut0(i,j,k)= Cstv_tau_8*( F_ru(i,j,k)-F_nu(i,j,k) - aaa2*
     $                 (F_gptx(i+1,j,k)-F_gptx(i,j,k)) / geomg_hx_8(i) )
         end do
         end do
*
         do j= j0, l_njv-pil_n
         do i= i0, in 
            F_vt0(i,j,k)= Cstv_tau_8*( F_rv(i,j,k)-F_nv(i,j,k) - aaa2*
     $                 (F_gptx(i,j+1,k) - F_gptx(i,j,k)) 
     $                  *geomg_cyv2_8(j)*geomg_invhsy_8(j) )
         end do
         end do
 600  continue
!$omp enddo
*
      endif
*************************************************************
*  $. Final back substitution after the nonlinear iteration * 
*************************************************************
*
      if ( .not. (F_itr .lt. F_itnlh) ) then
*
!$omp do
      do 700 k=1,l_nk

         if (.not.Cori_cornl_L) then
            do j= j0, jn 
            do i= i0, l_niu-pil_e
               F_ut0(i,j,k)= Cstv_tau_8*( F_ru(i,j,k)-F_nu(i,j,k) - aaa2*
     $                 (F_gptx(i+1,j,k)-F_gptx(i,j,k)) / geomg_hx_8(i) )
            end do
            end do
*
            do j= j0, l_njv-pil_n
            do i= i0, in 
               F_vt0(i,j,k)= Cstv_tau_8*( F_rv(i,j,k)-F_nv(i,j,k) - aaa2*
     $                 (F_gptx(i,j+1,k) - F_gptx(i,j,k)) 
     $                  *geomg_cyv2_8(j)*geomg_invhsy_8(j) )
            end do
            end do
         endif
*
*     Compute pi*-dot 
*     ~~~~~~~~~~~~~~~
         if ( (k.eq.1) .or. (k.eq.l_nk) ) then
            do j= j0, jn 
            do i= i0, in 
               F_psdt0(i,j,k) = 0.
            end do
            end do
         else
            tmp_8 = geomg_pib(k)/Cstv_tau_8
            do j= j0, jn 
            do i= i0, in 
               F_psdt0(i,j,k) = F_gxtx(i,j,k) - tmp_8*F_st0(i,j)
            end do
            end do
         endif
*
*     Compute total divergence, phi and T
*     ~~~~~~~~~~~~~~~~~~~~~~~~
         tmp_8 = geomg_dpib(k)/Cstv_tau_8
         do j= j0, jn 
         do i= i0, in 
            F_tdt0(i,j,k) = F_rcn  (i,j,k) - F_ncn(i,j,k) - tmp_8*F_st0(i,j)
            F_fit0(i,j,k) = F_fipt0(i,j,k) + Cstvr_fistr_8(k) + F_fis(i,j)
            F_tt0 (i,j,k) = F_tpt0 (i,j,k) + Cstv_tstr_8
         end do
         end do
*
 700  continue
!$omp enddo
      endif
!$omp end parallel
*
*     __________________________________________________________________
*
      return
      end