SUBROUTINE CVAR3(YDSPEC,YDCV,PGP3,PGP2,KCOMP,LDJBBAL)

!     CVAR3 : Transformation of model fields
!             Remark: content of this routine was in sqrtb.F90 until CY31.

!     Purpose: Transform from model variables
!     --------           to Jb-normalized departures w.r.t. background

!     Externals: see below.
!     ----------

!     Author.    W. HECKLEY    *ECMWF*
!     -------

!     Modifications.
!     --------------
!        W. HECKLEY    91:09:30  Change in call to STEPO
!        Bill Heckley  06:02:92 - Provision for use of mass variable P
!        Bill Heckley  04:03:93 - Horizontal Jg correlation computation now a
!                                 part of the control variable.
!        Bill Heckley  07:06:93   separation of code into lower level routines
!        Mike Fisher   95-01-20   LSUBFG and CALL MLTEPS
!        Mike Fisher   95-09-20   LMVCHV switch
!        Mats Hamrud   95-12-15   Remove NFGM .ne. 1, cleaning
!        Mike Fisher   96-05-30   Reverse order of CVARU2 and MLTEPS
!        F. Bouttier   96-07-17   Clean comments
!        F. Bouttier   96-12-13   Implement LSTABAL option
!        Mike Fisher   97-02-21   Simplified Kalman Filter
!        M. Siroka     98-05-13   LELAM for LSTABAL option
!        Mike Fisher 2000-10-26   Jb vertical coordinate
!        Mike Fisher 2001-12-03   Omega-equation balance operator
!        Y.Tremolet  2002-08-05   Use control_vectors.
!        M.Hamrud      01-Oct-2003 CY28 Cleaning
!        M.Fisher    17-Mar-2004 Pass a control vector rather than an array
!        R.El Ouaraini 18-Feb-2004 Beta-plane balance for Aladin
!        R. el Khatib  04-08-05   simplified interface to ebalbeta
!        G. Faure      20-Jan-2006 Non linear and omega balances for LELAM
!        Elias Holm    08-10-20   Add jbchvar call for variable              
!                                 transform (normalized humidity etc). 
!                                 Move Jb coordinate transform besides
!                                 fc-error normalization in cvargptl.
!        Y.Tremolet    27-Nov-2008 Option for no balance in stratosphere 
!        David Tan     07-Dec-2009 Correct zu for balance in stratosphere 
!     ------------------------------------------------------------------

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
USE YOMJG    , ONLY : LJBENER , &
 & RAMENER  ,BFACT1   ,BFACT2   ,BFACT, &
 & LJB_NONLINEAR_BALANCE, LJB_OMEGA_BALANCE, &
 & LJBBALBETA, LJB_UNIVARIATE, LBALSTRATO, NLEVBAL0, NLEVBAL1, LJB_NONLINEAR_CVHUM, LJB_NONLINEAR_CVO3
USE YOMSPJB  , ONLY : SP7VOR, SP7T
USE YOMCT0   , ONLY : LELAM
USE YEMLAP   , ONLY : NESM0
USE YOMLAP   , ONLY : NASM0
USE YOMDIM   , ONLY : NFLEVL   ,NFLSUR   ,NSMAX    ,NMSMAX   ,NSPEC2, NFLEVG
USE YOMMP    , ONLY : MYLEVS
USE CONTROL_VECTORS
USE SPECTRAL_FIELDS_MOD

!     ------------------------------------------------------------------

IMPLICIT NONE

TYPE(CONTROL_VECTOR), INTENT(INOUT) :: YDCV 
TYPE(SPECTRAL_FIELD), INTENT(INOUT) :: YDSPEC
REAL(KIND=JPRB), INTENT(INOUT) :: PGP3(:,:,:)
REAL(KIND=JPRB), INTENT(INOUT) :: PGP2(:,:,:)
INTEGER(KIND=JPIM), INTENT(IN) :: KCOMP
LOGICAL, OPTIONAL, INTENT(IN) :: LDJBBAL

!     ------------------------------------------------------------------

LOGICAL :: LLJBBAL
TYPE(SPECTRAL_FIELD) :: YLUNBAL
REAL(KIND=JPRB) :: ZZP(NFLSUR,NSPEC2), ZDIV(NFLEVL,NSPEC2)
INTEGER(KIND=JPIM) :: ii, il, jl
REAL(KIND=JPRB) :: zb,zu
REAL(KIND=JPRB) :: ZHOOK_HANDLE

!     ------------------------------------------------------------------

#include "balnonlintl.intfb.h"
#include "balomegatl.intfb.h"
#include "balstat.intfb.h"
#include "balverti.intfb.h"
#include "sqrtb.intfb.h"
#include "sqrtq.intfb.h"
#include "ebalbeta.intfb.h"
#include "ebalstat.intfb.h"
#include "ebalverti.intfb.h"
#include "ebalnonlintl.intfb.h"
#include "ebalomegatl.intfb.h"
#include "jbchvar.intfb.h"
#include "sualspajb.intfb.h"
!     ------------------------------------------------------------------

IF (LHOOK) CALL DR_HOOK('CVAR3',0,ZHOOK_HANDLE)

!     ------------------------------------------------------------------

!     1.    Gridpoint variable 'balance' transform and normalization
!           --------------------------------------------------------

IF (LJB_NONLINEAR_CVHUM .OR. LJB_NONLINEAR_CVO3) THEN
  CALL JBCHVAR(YDSPEC%TEM,PGP3)
ENDIF

!     ------------------------------------------------------------------
LLJBBAL=.true.
IF (PRESENT(LDJBBAL)) LLJBBAL=LDJBBAL
IF (LLJBBAL) THEN

! Switch off balance in stratosphere
  IF (.NOT.LBALSTRATO) THEN
    CALL SUALSPAJB(YLUNBAL)

    DO jl=1,NFLEVL
      il=MYLEVS(jl)
      IF (il<=NLEVBAL1) THEN
        YLUNBAL%SP3D(jl,:,:) = YDSPEC%SP3D(jl,:,:)
      ENDIF
    ENDDO

    DO jl=1,NFLEVL
      il=MYLEVS(jl)
      IF (il<=NLEVBAL0) THEN
        YDSPEC%SP3D(jl,:,:) = 0.0_JPRB
      ELSEIF (il<NLEVBAL1) THEN
        zb=SQRT(REAL(il-NLEVBAL0)/REAL(NLEVBAL1-NLEVBAL0))
        YDSPEC%SP3D(jl,:,:) = zb*YDSPEC%SP3D(jl,:,:)
      ENDIF
    ENDDO
  ENDIF

!     2.    (T,ps) to P and balance transforms
!           ----------------------------------

  IF (.NOT.LJB_UNIVARIATE .AND. .NOT.(LJBENER.OR.(RAMENER >= 0))) THEN
!         Integrated inverse statistical balance option :
!         Infer unbalanced part of (T,ps) and divergence from vorticity
    IF (LELAM) THEN
      IF (LJB_OMEGA_BALANCE) THEN
        CALL EBALOMEGATL (YDSPEC%VOR,YDSPEC%TEM,SP7VOR,SP7T,ZDIV)
        YDSPEC%DIV(:,:) = YDSPEC%DIV(:,:) - ZDIV(:,:) 
      ENDIF
      IF (LJB_NONLINEAR_BALANCE) THEN
        CALL EBALNONLINTL (YDSPEC%VOR,SP7VOR,ZZP)
      ELSEIF (LJBBALBETA) THEN
        CALL EBALBETA(YDSPEC%VOR,ZZP)
      ELSE
        CALL EBALSTAT(NMSMAX,NESM0,NSPEC2,YDSPEC%VOR,ZZP,BFACT)
      ENDIF
      CALL EBALVERTI(ZZP,YDSPEC)
    ELSE
      IF (LJB_OMEGA_BALANCE) THEN
        CALL BALOMEGATL (YDSPEC%VOR,YDSPEC%TEM,SP7VOR,SP7T,ZDIV)
        YDSPEC%DIV(:,:) = YDSPEC%DIV(:,:) - ZDIV(:,:) 
      ENDIF
      IF (LJB_NONLINEAR_BALANCE) THEN
        CALL BALNONLINTL (YDSPEC%VOR,SP7VOR,ZZP)
      ELSE
        CALL BALSTAT(NFLEVL,NSMAX,NASM0,NSPEC2,YDSPEC%VOR,YDSPEC%DIV,&
                   & ZZP,BFACT1,BFACT2)
      ENDIF
      CALL BALVERTI(ZZP,YDSPEC)
    ENDIF
  ENDIF

! Switch off balance in stratosphere
  IF (.NOT.LBALSTRATO) THEN
    DO jl=1,NFLEVL
      il=MYLEVS(jl)
      IF (il<=NLEVBAL0) THEN
        YDSPEC%SP3D(jl,:,:) = YLUNBAL%SP3D(jl,:,:)
      ELSEIF (il<NLEVBAL1) THEN
        zb=SQRT(REAL(il-NLEVBAL0)/REAL(NLEVBAL1-NLEVBAL0))
        zu=1.0_JPRB-zb*zb
        YDSPEC%SP3D(jl,:,:) = zb*YDSPEC%SP3D(jl,:,:) + zu*YLUNBAL%SP3D(jl,:,:)
      ENDIF
    ENDDO

    CALL DEALLOCATE_SPEC(YLUNBAL)
  ENDIF

ENDIF

!     ------------------------------------------------------------------

!     3.    Square root of correlation operator
!           -----------------------------------
IF (kcomp==0) THEN
  CALL SQRTB(YDSPEC,YDCV)
ELSE
  il=YDSPEC%nspsizel
  ii=(kcomp-1)*il
  CALL SQRTQ(YDSPEC)
  YDCV%MODERR(ii+1:ii+il)=YDSPEC
ENDIF

!     ------------------------------------------------------------------

IF (LHOOK) CALL DR_HOOK('CVAR3',1,ZHOOK_HANDLE)
END SUBROUTINE CVAR3
