SUBROUTINE cvarbcinad
!-----------------------------------------------------------------------
!   CVARBCINAD - Adjoint inverse change-of-variable for variational bias 
!   parameters

!   Purpose.
!   --------
!   Applies inverse change-of-variable to the control vector section
!   associated with the observation bias parameters

!   Interface.
!   ----------
!   CALL cvarbcinad ()

!   Implicit input:
!      YVARBC

!   Implicit output:
!      YVARBC

!   Author.
!   -------
!   Dick Dee (ECMWF)

!   Modifications.
!   --------------
!   Original       : 19-Mar-2004
!   P.Burton       : 29-Sep-2004 LVARBC cleanup and
!                                 changed MPL_ALLREDUCE to LDREPROD=.true.
!   G. Mozdzynski  : 03-Jun-2009 VarBC reproducibility rework
!   T. Wilhelmsson : 26-Feb-2010 More VarBC reproducibility rework
!-----------------------------------------------------------------------

USE parkind1, ONLY : JPIM, JPRB
USE yomhook,  ONLY : lhook, dr_hook
USE varbc_setup, ONLY : YVARBC, NOBGROUP, NOBPARAM, JPMXNPARAM, APARAMS_COMP, NPARAMS_COMP
USE YOMVAR, ONLY : LREPRO4DVAR
USE mpl_module
USE ORDER_INDEPENDENT_SUMMATION_MOD, ONLY : ORDER_INDEP_GLOBAL_SUM2
USE yomct0, ONLY : NPROC

IMPLICIT NONE

INTEGER(KIND=JPIM) :: jg, jp, inp, ibeg, iend, inparams(JPMXNPARAM)
REAL(KIND=JPRB)    :: zp(JPMXNPARAM)
REAL(KIND=JPRB)    :: zhook_handle

REAL(KIND=JPRB), ALLOCATABLE :: zparams(:)
INTEGER(KIND=JPIM) :: ib(NOBGROUP),ie(NOBGROUP)

IF (lhook) CALL DR_HOOK('CVARBCINAD',0,zhook_handle)

IF( .NOT.LREPRO4DVAR )THEN

  ALLOCATE(zparams(NOBPARAM))
  ibeg = 1
  DO jg = 1, NOBGROUP
    iend = ibeg + YVARBC(jg)%NPARAM - 1
    ib(jg)=ibeg
    ie(jg)=iend
    ibeg = iend + 1
  ENDDO
  CALL GSTATS(1447,0)
!$OMP PARALLEL DO SCHEDULE(STATIC) PRIVATE(jg)
  DO jg = 1, NOBGROUP
    zparams(ib(jg):ie(jg)) = YVARBC(jg)%APARAMS
  ENDDO
!$OMP END PARALLEL DO
  CALL GSTATS(1447,1)
  CALL GSTATS(518,0)
  CALL MPL_ALLREDUCE(zparams, 'sum', ldreprod=.TRUE.,CDSTRING='CVARBCINAD:')
  CALL GSTATS(518,1)
  CALL GSTATS(1447,0)
!$OMP PARALLEL DO SCHEDULE(STATIC) PRIVATE(jg,inp,jp,zp)
  DO jg = 1, NOBGROUP
    YVARBC(jg)%APARAMS =  zparams(ib(jg):ie(jg))
    inp = YVARBC(jg)%NPARAM
    DO jp = 1, inp
      zp(jp) = SUM(YVARBC(jg)%ACVARIN(jp,:) * YVARBC(jg)%APARAMS(1:inp))
    ENDDO
    YVARBC(jg)%APARAMS = zp(1:inp)
  ENDDO
!$OMP END PARALLEL DO
  CALL GSTATS(1447,1)
  DEALLOCATE(zparams)

ELSE

  DO jg = 1, NOBGROUP
    inp = YVARBC(jg)%NPARAM
    CALL GSTATS(518,0)
    inparams(1:inp) = nparams_comp(1:inp,jg)
    CALL order_indep_global_sum2(aparams_comp(:,:,jg),zp,inp,1,inparams)
    YVARBC(jg)%APARAMS(1:inp) = YVARBC(jg)%APARAMS(1:inp) + zp(1:inp) 
    CALL GSTATS(518,1)
    DO jp = 1, inp
      zp(jp) = SUM(YVARBC(jg)%ACVARIN(jp,:) * YVARBC(jg)%APARAMS(1:inp))
    ENDDO
    YVARBC(jg)%APARAMS = zp(1:inp)
  ENDDO

  DEALLOCATE(APARAMS_COMP,NPARAMS_COMP) ! Was allocated in taskobad

ENDIF

IF (lhook) CALL DR_HOOK('CVARBCINAD',1,zhook_handle)

END SUBROUTINE cvarbcinad
