diff --git a/src/ZSOLVER/tridiag_thermo.f90 b/src/ZSOLVER/tridiag_thermo.f90
new file mode 100644
index 0000000000000000000000000000000000000000..95e86abe02d31200869309a613f7b86efe447094
--- /dev/null
+++ b/src/ZSOLVER/tridiag_thermo.f90
@@ -0,0 +1,464 @@
+!MNH_LIC Copyright 2003-2020 CNRS, Meteo-France and Universite Paul Sabatier
+!MNH_LIC This is part of the Meso-NH software governed by the CeCILL-C licence
+!MNH_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
+!MNH_LIC for details. version 1.
+!-----------------------------------------------------------------
+!     ###################
+      MODULE MODI_TRIDIAG_THERMO
+!     ###################
+!        
+INTERFACE
+!        
+       SUBROUTINE TRIDIAG_THERMO(KKA,KKU,KKL,PVARM,PF,PDFDDTDZ,PTSTEP,PIMPL,  &
+                                 PDZZ,PRHODJ,PVARP             )
+!
+INTEGER,                INTENT(IN)   :: KKA           !near ground array index  
+INTEGER,                INTENT(IN)   :: KKU           !uppest atmosphere array index
+INTEGER,                INTENT(IN)   :: KKL           !vert. levels type 1=MNH -1=AR
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PVARM   ! variable at t-1      at mass point
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PF      ! flux in dT/dt=-dF/dz at flux point
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PDFDDTDZ! dF/d(dT/dz)          at flux point
+REAL,                   INTENT(IN) :: PTSTEP  ! Double time step
+REAL,                   INTENT(IN) :: PIMPL   ! implicit weight
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PDZZ    ! Dz                   at flux point
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PRHODJ  ! (dry rho)*J          at mass point
+!
+REAL, DIMENSION(:,:,:), INTENT(OUT):: PVARP   ! variable at t+1      at mass point
+!
+END SUBROUTINE TRIDIAG_THERMO
+!
+END INTERFACE
+!
+END MODULE MODI_TRIDIAG_THERMO 
+!
+!      #################################################
+       SUBROUTINE TRIDIAG_THERMO(KKA,KKU,KKL,PVARM,PF,PDFDDTDZ,PTSTEP,PIMPL,  &
+                                 PDZZ,PRHODJ,PVARP             )
+!      #################################################
+!
+!
+!!****   *TRIDIAG_THERMO* - routine to solve a time implicit scheme
+!!
+!!
+!!     PURPOSE
+!!     -------
+!        The purpose of this routine is to give a field PVARP at t+1, by 
+!      solving an implicit TRIDIAGonal system obtained by the 
+!      discretization of the vertical turbulent diffusion. It should be noted 
+!      that the degree of implicitness can be varied (PIMPL parameter) and that
+!      the function of F(dT/dz) must have been linearized.
+!      PVARP is localized at a mass point.
+!
+!!**   METHOD
+!!     ------
+!!
+!!        [T(+) - T(-)]/2Dt = -d{ F + dF/d(dT/dz) * [impl*dT/dz(+) + expl* dT/dz(-)] }/dz
+!!
+!!     It is discretized as follows:
+!!
+!!    PRHODJ(k)*PVARP(k)/PTSTEP
+!!              = 
+!!    PRHODJ(k)*PVARM(k)/PTSTEP 
+!!  - (PRHODJ(k+1)+PRHODJ(k)  )/2. * PF(k+1)/PDZZ(k+1)
+!!  + (PRHODJ(k)  +PRHODJ(k-1))/2. * PF(k)  /PDZZ(k)
+!!  + (PRHODJ(k+1)+PRHODJ(k)  )/2. * ZEXPL* PDFDDTDZ(k+1) * PVARM(k+1)/PDZZ(k+1)**2
+!!  - (PRHODJ(k+1)+PRHODJ(k)  )/2. * PIMPL* PDFDDTDZ(k+1) * PVARP(k+1)/PDZZ(k+1)**2
+!!  - (PRHODJ(k+1)+PRHODJ(k)  )/2. * ZEXPL* PDFDDTDZ(k+1) * PVARM(k)  /PDZZ(k+1)**2
+!!  + (PRHODJ(k+1)+PRHODJ(k)  )/2. * PIMPL* PDFDDTDZ(k+1) * PVARP(k)  /PDZZ(k+1)**2
+!!  - (PRHODJ(k)  +PRHODJ(k-1))/2. * ZEXPL* PDFDDTDZ(k)   * PVARM(k)  /PDZZ(k)**2
+!!  + (PRHODJ(k)  +PRHODJ(k-1))/2. * PIMPL* PDFDDTDZ(k)   * PVARP(k)  /PDZZ(k)**2
+!!  + (PRHODJ(k)  +PRHODJ(k-1))/2. * ZEXPL* PDFDDTDZ(k)   * PVARM(k-1)/PDZZ(k)**2
+!!  - (PRHODJ(k)  +PRHODJ(k-1))/2. * PIMPL* PDFDDTDZ(k)   * PVARP(k-1)/PDZZ(k)**2
+!!
+!!
+!!    The system to solve is:
+!!
+!!      A*PVARP(k-1) + B*PVARP(k) + C*PVARP(k+1) = Y(k)
+!!
+!!
+!!    The RHS of the linear system in PVARP writes:
+!!
+!! y(k)    = PRHODJ(k)*PVARM(k)/PTSTEP
+!!  - (PRHODJ(k+1)+PRHODJ(k)  )/2. * PF(k+1)/PDZZ(k+1)
+!!  + (PRHODJ(k)  +PRHODJ(k-1))/2. * PF(k)  /PDZZ(k)
+!!  + (PRHODJ(k+1)+PRHODJ(k)  )/2. * ZEXPL* PDFDDTDZ(k+1) * PVARM(k+1)/PDZZ(k+1)**2
+!!  - (PRHODJ(k+1)+PRHODJ(k)  )/2. * ZEXPL* PDFDDTDZ(k+1) * PVARM(k)  /PDZZ(k+1)**2
+!!  - (PRHODJ(k)  +PRHODJ(k-1))/2. * ZEXPL* PDFDDTDZ(k)   * PVARM(k)  /PDZZ(k)**2
+!!  + (PRHODJ(k)  +PRHODJ(k-1))/2. * ZEXPL* PDFDDTDZ(k)   * PVARM(k-1)/PDZZ(k)**2
+!!
+!!                      
+!!        Then, the classical TRIDIAGonal algorithm is used to invert the 
+!!     implicit operator. Its matrix is given by:
+!!
+!!     ( b(ikb)   c(ikb)      0        0        0         0        0        0  )
+!!     (   0      a(ikb+1) b(ikb+1) c(ikb+1)    0  ...    0        0        0  ) 
+!!     (   0         0     a(ikb+2) b(ikb+2) c(ikb+2).    0        0        0  ) 
+!!      .......................................................................
+!!     (   0   ...   0     a(k)     b(k)     c(k)         0   ...  0        0  ) 
+!!      .......................................................................
+!!     (   0         0        0        0        0 ...a(ike-1) b(ike-1) c(ike-1))
+!!     (   0         0        0        0        0 ...     0   a(ike)   b(ike)  )
+!!
+!!     ikb and ike represent the first and the last inner mass levels of the
+!!     model. The coefficients are:
+!!         
+!! a(k) = + (PRHODJ(k)  +PRHODJ(k-1))/2. * PIMPL* PDFDDTDZ(k)  /PDZZ(k)**2
+!! b(k) =    PRHODJ(k) / PTSTEP
+!!        - (PRHODJ(k+1)+PRHODJ(k)  )/2. * PIMPL* PDFDDTDZ(k+1)/PDZZ(k+1)**2
+!!        - (PRHODJ(k)  +PRHODJ(k-1))/2. * PIMPL* PDFDDTDZ(k)  /PDZZ(k)**2
+!! c(k) = + (PRHODJ(k+1)+PRHODJ(k)  )/2. * PIMPL* PDFDDTDZ(k+1)/PDZZ(k+1)**2
+!!
+!!          for all k /= ikb or ike
+!!
+!!
+!! b(ikb) =  PRHODJ(ikb) / PTSTEP
+!!          -(PRHODJ(ikb+1)+PRHODJ(ikb))/2.*PIMPL*PDFDDTDZ(ikb+1)/PDZZ(ikb+1)**2
+!! c(ikb) = +(PRHODJ(ikb+1)+PRHODJ(ikb))/2.*PIMPL*PDFDDTDZ(ikb+1)/PDZZ(ikb+1)**2
+!!
+!! b(ike) =  PRHODJ(ike) / PTSTEP
+!!          -(PRHODJ(ike)+PRHODJ(ike-1))/2.*PIMPL*PDFDDTDZ(ike)/PDZZ(ike)**2
+!! a(ike) = +(PRHODJ(ike)+PRHODJ(ike-1))/2.*PIMPL*PDFDDTDZ(ike)/PDZZ(ike)**2
+!!
+!!
+!!     EXTERNAL
+!!     --------
+!!
+!!       NONE
+!!
+!!     IMPLICIT ARGUMENTS
+!!     ------------------
+!!
+!!     REFERENCE
+!!     ---------
+!!       Press et al: Numerical recipes (1986) Cambridge Univ. Press
+!!
+!!     AUTHOR
+!!     ------
+!!       V. Masson         * Meteo-France *   
+!! 
+!!     MODIFICATIONS
+!!     -------------
+!!       Original        04/2003 (from tridiag.f90)
+!!       M.Moge          04/2016 Use openACC directives to port the TURB part of Meso-NH on GPU
+!! ---------------------------------------------------------------------
+!
+!*       0. DECLARATIONS
+!
+USE MODD_PARAMETERS, ONLY : JPVEXT_TURB
+
+use mode_mppdb
+
+#ifndef MNH_OPENACC
+USE MODI_SHUMAN
+#else
+USE MODI_SHUMAN_DEVICE
+#endif
+#ifdef MNH_BITREP
+USE MODI_BITREP
+#endif
+!
+#ifdef MNH_OPENACC
+USE MODE_MNH_ZWORK , ONLY : MNH_ALLOCATE_ZT3D , MNH_REL_ZT3D , MNH_ALLOCATE_ZT2D, &
+                            MNH_CHECK_IN_ZT3D,MNH_CHECK_OUT_ZT3D
+#endif
+!
+IMPLICIT NONE
+!
+!
+!*       0.1 declarations of arguments
+!
+INTEGER,              INTENT(IN)   :: KKA     !near ground array index  
+INTEGER,              INTENT(IN)   :: KKU     !uppest atmosphere array index
+INTEGER,              INTENT(IN)   :: KKL     !vert. levels type 1=MNH -1=ARO
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PVARM   ! variable at t-1      at mass point
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PF      ! flux in dT/dt=-dF/dz at flux point
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PDFDDTDZ! dF/d(dT/dz)          at flux point
+REAL,                   INTENT(IN) :: PTSTEP  ! Double time step
+REAL,                   INTENT(IN) :: PIMPL   ! implicit weight
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PDZZ    ! Dz                   at flux point
+REAL, DIMENSION(:,:,:), INTENT(IN) :: PRHODJ  ! (dry rho)*J          at mass point
+!
+REAL, DIMENSION(:,:,:), INTENT(OUT):: PVARP   ! variable at t+1      at mass point
+!
+!*       0.2 declarations of local variables
+!
+REAL, DIMENSION(:,:,:), pointer , contiguous :: ZRHODJ_DFDDTDZ_O_DZ2
+REAL, DIMENSION(:,:,:), pointer , contiguous :: ZMZM_RHODJ
+REAL, DIMENSION(:,:,:), pointer , contiguous :: ZA, ZB, ZC
+REAL, DIMENSION(:,:,:), pointer , contiguous :: ZY ,ZGAM
+                                         ! RHS of the equation, 3D work array
+INTEGER :: IZRHODJ_DFDDTDZ_O_DZ2,IZMZM_RHODJ,IZA,IZB,IZC,IZY,IZGAM
+REAL, DIMENSION(:,:), pointer , contiguous   :: ZBET
+INTEGER :: IZBET
+                                         ! 2D work array
+INTEGER             :: JI,JJ,JK      ! loop counter
+INTEGER             :: IKB,IKE       ! inner vertical limits
+INTEGER             :: IKT          ! array size in k direction
+INTEGER             :: IKTB,IKTE    ! start, end of k loops in physical domain 
+!
+!
+#ifdef MNH_OPENACC
+REAL, DIMENSION(:,:,:), pointer , contiguous :: ZTMP1_DEVICE
+INTEGER :: IZTMP1_DEVICE
+#endif
+
+INTEGER  :: JIU,JJU,JKU
+
+! ---------------------------------------------------------------------------
+
+!$acc data present( PVARM, PF, PDFDDTDZ, PDZZ, PRHODJ, PVARP )
+
+if ( mppdb_initialized ) then
+  !Check all in arrays
+  call Mppdb_check( pvarm,    "Tridiag_thermo beg:pvarm"    )
+  call Mppdb_check( pf,       "Tridiag_thermo beg:pf"       )
+  call Mppdb_check( pdfddtdz, "Tridiag_thermo beg:pdfddtdz" )
+  call Mppdb_check( pdzz,     "Tridiag_thermo beg:pdzz"     )
+  call Mppdb_check( prhodj,   "Tridiag_thermo beg:prhodj"   )
+end if
+
+JIU =  size( pvarm, 1 )
+JJU =  size( pvarm, 2 )
+JKU =  size( pvarm, 3 )
+
+#ifndef MNH_OPENACC
+allocate( zrhodj_dfddtdz_o_dz2(JIU,JJU,JKU ) )
+allocate( zmzm_rhodj          (JIU,JJU,JKU ) )
+allocate( za                  (JIU,JJU,JKU ) )
+allocate( zb                  (JIU,JJU,JKU ) )
+allocate( zc                  (JIU,JJU,JKU ) )
+allocate( zy                  (JIU,JJU,JKU ) )
+allocate( zgam                (JIU,JJU,JKU ) )
+allocate( zbet                (JIU,JJU ) )
+#else
+CALL MNH_CHECK_IN_ZT3D("TRIDIAG_THERMO")
+izrhodj_dfddtdz_o_dz2 = MNH_ALLOCATE_ZT3D( zrhodj_dfddtdz_o_dz2,JIU,JJU,JKU )
+izmzm_rhodj           = MNH_ALLOCATE_ZT3D( zmzm_rhodj          ,JIU,JJU,JKU )
+iza                   = MNH_ALLOCATE_ZT3D( za                  ,JIU,JJU,JKU )
+izb                   = MNH_ALLOCATE_ZT3D( zb                  ,JIU,JJU,JKU )
+izc                   = MNH_ALLOCATE_ZT3D( zc                  ,JIU,JJU,JKU )
+izy                   = MNH_ALLOCATE_ZT3D( zy                  ,JIU,JJU,JKU )
+izgam                 = MNH_ALLOCATE_ZT3D( zgam                ,JIU,JJU,JKU )
+izbet                 = MNH_ALLOCATE_ZT2D( zbet                ,JIU,JJU )
+#endif
+
+#ifdef MNH_OPENACC
+iztmp1_device = MNH_ALLOCATE_ZT3D( ztmp1_device,JIU,JJU,JKU )
+#endif
+
+!$acc data present( zrhodj_dfddtdz_o_dz2, zmzm_rhodj, za, zb, zc, zy, zgam, zbet, ztmp1_device )
+!
+!*      1.  Preliminaries
+!           -------------
+!
+IKT=SIZE(PVARM,3)          
+IKTB=1+JPVEXT_TURB              
+IKTE=IKT-JPVEXT_TURB
+IKB=KKA+JPVEXT_TURB*KKL
+IKE=KKU-JPVEXT_TURB*KKL
+!
+#ifndef MNH_OPENACC
+ZMZM_RHODJ = MZM(PRHODJ)
+#else
+CALL MZM_DEVICE(PRHODJ,ZMZM_RHODJ)
+#endif
+!$acc kernels ! async
+#ifndef MNH_BITREP
+ZRHODJ_DFDDTDZ_O_DZ2 = ZMZM_RHODJ*PDFDDTDZ/PDZZ**2
+#else
+!$acc loop independent collapse(3)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU,JK=1:JKU) 
+   ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,JK) = ZMZM_RHODJ(JI,JJ,JK)*PDFDDTDZ(JI,JJ,JK)/BR_P2(PDZZ(JI,JJ,JK))
+END DO !CONCURRENT   
+#endif
+!$acc end kernels
+!
+!$acc kernels ! async
+ZA=0.
+ZB=0.
+ZC=0.
+ZY=0.
+!$acc end kernels
+! acc wait
+!
+!
+!*      2.  COMPUTE THE RIGHT HAND SIDE
+!           ---------------------------
+!
+!$acc kernels ! async
+!$acc loop independent collapse(2)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)
+ZY(JI,JJ,IKB) = PRHODJ(JI,JJ,IKB)*PVARM(JI,JJ,IKB)/PTSTEP                  &
+    - ZMZM_RHODJ(JI,JJ,IKB+KKL) * PF(JI,JJ,IKB+KKL)/PDZZ(JI,JJ,IKB+KKL)    &
+    + ZMZM_RHODJ(JI,JJ,IKB  ) * PF(JI,JJ,IKB  )/PDZZ(JI,JJ,IKB  )          &
+    + ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,IKB+KKL) * PIMPL * PVARM(JI,JJ,IKB+KKL) &
+    - ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,IKB+KKL) * PIMPL * PVARM(JI,JJ,IKB  )
+END DO !CONCURRENT
+!$acc end kernels
+!
+!$acc kernels ! async
+!$acc loop independent collapse(3)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU,JK=IKTB+1:IKTE-1)
+  ZY(JI,JJ,JK) = PRHODJ(JI,JJ,JK)*PVARM(JI,JJ,JK)/PTSTEP                 &
+    - ZMZM_RHODJ(JI,JJ,JK+KKL) * PF(JI,JJ,JK+KKL)/PDZZ(JI,JJ,JK+KKL)     &
+    + ZMZM_RHODJ(JI,JJ,JK  ) * PF(JI,JJ,JK  )/PDZZ(JI,JJ,JK  )           &
+    + ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,JK+KKL) * PIMPL * PVARM(JI,JJ,JK+KKL) &
+    - ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,JK+KKL) * PIMPL * PVARM(JI,JJ,JK  )   &
+    - ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,JK    ) * PIMPL * PVARM(JI,JJ,JK  )   &
+    + ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,JK    ) * PIMPL * PVARM(JI,JJ,JK-KKL)
+END DO !CONCURRENT
+!$acc end kernels
+! 
+!$acc kernels ! async
+!$acc loop independent collapse(2)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)
+ZY(JI,JJ,IKE) = PRHODJ(JI,JJ,IKE)*PVARM(JI,JJ,IKE)/PTSTEP               &
+    - ZMZM_RHODJ(JI,JJ,IKE+KKL) * PF(JI,JJ,IKE+KKL)/PDZZ(JI,JJ,IKE+KKL) &
+    + ZMZM_RHODJ(JI,JJ,IKE  ) * PF(JI,JJ,IKE  )/PDZZ(JI,JJ,IKE  )       &
+    - ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,IKE ) * PIMPL * PVARM(JI,JJ,IKE  )   &
+    + ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,IKE ) * PIMPL * PVARM(JI,JJ,IKE-KKL)
+END DO !CONCURRENT
+!$acc end kernels
+!
+! acc wait
+!
+!*       3.  INVERSION OF THE TRIDIAGONAL SYSTEM
+!            -----------------------------------
+!
+IF ( PIMPL > 1.E-10 ) THEN
+!
+!*       3.1 arrays A, B, C
+!            --------------
+!
+!$acc kernels ! async
+!$acc loop independent collapse(2)   
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)   
+  ZB(JI,JJ,IKB) =   PRHODJ(JI,JJ,IKB)/PTSTEP                   &
+                - ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,IKB+KKL) * PIMPL
+END DO !CONCURRENT 
+!$acc end kernels
+!
+!$acc kernels ! async
+!$acc loop independent collapse(2)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)
+  ZC(JI,JJ,IKB) =   ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,IKB+KKL) * PIMPL
+END DO !CONCURRENT
+!$acc end kernels
+!
+!$acc kernels ! async
+!$acc loop independent collapse(3)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU,JK=IKTB+1:IKTE-1)
+  ZA(JI,JJ,JK) =   ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,JK) * PIMPL
+  ZB(JI,JJ,JK) =   PRHODJ(JI,JJ,JK)/PTSTEP                        &
+                          - ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,JK+KKL) * PIMPL &
+                          - ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,JK) * PIMPL
+  ZC(JI,JJ,JK) =   ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,JK+KKL) * PIMPL
+END DO !CONCURRENT
+!$acc end kernels
+!
+!$acc kernels ! async
+!$acc loop independent collapse(2)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)
+  ZA(JI,JJ,IKE) =   ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,IKE  ) * PIMPL
+  ZB(JI,JJ,IKE) =   PRHODJ(JI,JJ,IKE)/PTSTEP                   &
+                - ZRHODJ_DFDDTDZ_O_DZ2(JI,JJ,IKE  ) * PIMPL
+END DO !CONCURRENT
+!$acc end kernels
+!
+! acc wait
+!
+!
+!*       3.2 going up
+!            --------
+!
+!$acc kernels
+!$acc loop independent collapse(2)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)
+  ZBET(JI,JJ) = ZB(JI,JJ,IKB)  ! bet = b(ikb)
+  PVARP(JI,JJ,IKB) = ZY(JI,JJ,IKB) / ZBET(JI,JJ)
+END DO !CONCURRENT
+!
+!$acc loop seq
+DO JK = IKB+KKL,IKE-KKL,KKL
+   !$acc loop independent collapse(2)
+   ! acc loop gang, vector collapse(2)
+   DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)
+   !DO JJ=1,JJU
+   !   DO JI=1,JIU     
+      ZGAM(JI,JJ,JK) = ZC(JI,JJ,JK-KKL) / ZBET(JI,JJ)  
+      ! gam(k) = c(k-1) / bet
+      ZBET(JI,JJ)    = ZB(JI,JJ,JK) - ZA(JI,JJ,JK) * ZGAM(JI,JJ,JK)
+      ! bet = b(k) - a(k)* gam(k)  
+      PVARP(JI,JJ,JK)= ( ZY(JI,JJ,JK) - ZA(JI,JJ,JK) * PVARP(JI,JJ,JK-KKL) ) / ZBET(JI,JJ)
+      ! res(k) = (y(k) -a(k)*res(k-1))/ bet
+   !   END DO
+   !END DO
+   END DO !CONCURRENT 
+END DO
+! special treatment for the last level
+!$acc loop independent collapse(2)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)
+      ZGAM(JI,JJ,IKE) = ZC(JI,JJ,IKE-KKL) / ZBET(JI,JJ) 
+      ! gam(k) = c(k-1) / bet
+      ZBET(JI,JJ)     = ZB(JI,JJ,IKE) - ZA(JI,JJ,IKE) * ZGAM(JI,JJ,IKE)
+      ! bet = b(k) - a(k)* gam(k)  
+      PVARP(JI,JJ,IKE)= ( ZY(JI,JJ,IKE) - ZA(JI,JJ,IKE) * PVARP(JI,JJ,IKE-KKL) ) / ZBET(JI,JJ)
+      ! res(k) = (y(k) -a(k)*res(k-1))/ bet 
+END DO !CONCURRENT
+!
+!*       3.3 going down
+!            ----------
+!
+!$acc loop seq
+DO JK = IKE-KKL,IKB,-1*KKL
+   !$acc loop independent collapse(2)
+   ! acc loop gang, vector collapse(2)
+   DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)
+      PVARP(JI,JJ,JK) = PVARP(JI,JJ,JK) - ZGAM(JI,JJ,JK+KKL) * PVARP(JI,JJ,JK+KKL)
+   END DO !CONCURRENT
+END DO
+!$acc end kernels
+!
+ELSE
+! 
+!$acc kernels
+!$acc loop independent collapse(3)   
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU,JK=IKTB:IKTE)   
+   PVARP(JI,JJ,JK) = ZY(JI,JJ,JK) * PTSTEP / PRHODJ(JI,JJ,JK)
+END DO !CONCURRENT
+!$acc end kernels
+!
+END IF 
+!
+!
+!*       4.  FILL THE UPPER AND LOWER EXTERNAL VALUES
+!            ----------------------------------------
+!
+!$acc kernels
+!$acc loop independent collapse(2)
+DO CONCURRENT ( JI=1:JIU,JJ=1:JJU)
+   PVARP(JI,JJ,KKA)=PVARP(JI,JJ,IKB)
+   PVARP(JI,JJ,KKU)=PVARP(JI,JJ,IKE)
+END DO !CONCURRENT
+!$acc end kernels
+
+if ( mppdb_initialized ) then
+  !Check all out arrays
+  call Mppdb_check( pvarp, "Tridiag_thermo end:pvarp" )
+end if
+
+!$acc end data
+
+#ifndef MNH_OPENACC
+deallocate (zrhodj_dfddtdz_o_dz2,zmzm_rhodj,za,zb,zc,zy,zgam,zbet)
+#else
+CALL MNH_REL_ZT3D(IZRHODJ_DFDDTDZ_O_DZ2,IZMZM_RHODJ,IZA,IZB,IZC,IZY,IZGAM,&
+                  IZBET,iztmp1_device)
+CALL MNH_CHECK_OUT_ZT3D("TRIDIAG_THERMO")
+#endif
+
+!$acc end data
+
+!-------------------------------------------------------------------------------
+!
+END SUBROUTINE TRIDIAG_THERMO