SUBROUTINE  CTR3D_CG
C===================================================================
C===========       3DVAR with the Conjugate Gradient  ==============
C===================================================================

      IMPLICIT NONE

      include 'champ.cdk'
      include 'chobs.cdk'


      INTEGER KDIM,INCRM,NINCRM
      INTEGER KMIN,KMAX,KRANGE 
      INTEGER IMODE,ISIMMAX,NGUESS
      INTEGER KINDIC,IR,CMP,PTFLAG
      INTEGER IZ(5)
      INTEGER II

      PARAMETER(KDIM=4096) 

      REAL*8 XX(KDIM),XX1(KDIM),Xb(KDIM)
      REAL*8 GX(KDIM),JX,PX(KDIM),PY(KDIM)      
      REAL*8 ZZS(1)

      REAL*8 ZXMIN,ZDF1,ZEPS,RE,IM,KX,KY,KWW
      REAL*8 XXO(KDIM)
      REAL*8 DLALPHA,DLGNORM,JX0,JXF,ZTEST
      LOGICAL VAR



C     Variables needed for the Conjugate Gradient
C     -------------------------------------------

      integer itermax,impres,mode,preco,npmat0,m0,nilm0,nwlm0
      integer bfgsb,npmat1,m1,nilm1,nwlm1,select, imtra
      integer kmode(3), izs(1), nulout
      real*8 dl_u(KDIM), b(KDIM), a(1)
      real*8 x2(KDIM), b2(KDIM),ilm0(1),ilm1(1)
      real*8 pmat0(KDIM,KDIM), pmat1(KDIM,KDIM)  
      real*8 zeps1, zzsunused(1),dlds(1),wlm0(12*KDIM+7),wlm1(12*KDIM+7)
      real*8 zepsneg
      real*8 dl_vatra(6*KDIM + 6)
      logical two
 
      integer i,j
      real*8  mean,somme

      EXTERNAL mv3dvar


C      Settings for the Conjugate Gradient
C      -----------------------------------

         m0 = 6 
         m1 = 6
         nwlm0 = 12*KDIM + 7
         nwlm1 = 12*KDIM + 7
         npmat0 = KDIM**2
         npmat1 = KDIM**2
         imtra = 6*KDIM + 6

         two = .false.
         preco = 0
         bfgsb = 0
         select = 0
         kmode(1) = 0 
         kmode(2) = 0
         kmode(3) = 0

         IMPRES = 5
         DO II =1,KDIM
            PX(II) = 0.0
            XX(II) = 0.0
            GX(II) = 0.0
            Xb(II) = 0.0
         END DO

         NINCRM  = 1
         NGUESS = 0
         NOITR   = 0
         NOSTR   = 1
         NULOUT  = 23
         PTFLAG  = 0
         RMFLAG  = 1

         zeps1 = 0.1E-3
         zepsneg = .1E-9
         itermax = 200 

         VAR = .true.

      CALL SETTING

      open (21,file='cougra.dat',status='unknown')
      open (22,file='couzqs.dat',status='unknown')
      open (24,file='couzqsl.dat',status='unknown')
      open (10,file='specal.dat',status='unknown')
      

C     Number of control variables 
C     ---------------------------

      NCO=0
      DO IKX=1,IKTX
      DO IKY=1,IKTY
        IF (L(IKX+KTX,IKY).EQ.1) THEN
         NCO = NCO + 2
        ENDIF
      ENDDO
      ENDDO
      NCO = NCO*2

C     Zeroing terms
C     -------------

      DO IKX=1,IKTX
      DO IKY=1,IKTY
           ZO(IKX,IKY) = CMPLX(0.,0.)
           SO(IKX,IKY) = CMPLX(0.,0.)
      ENDDO
      ENDDO

C     Get observations
C     ----------------

      CALL OBSERVATIONS 
       print*, 'Tout va bien (1)'
C     Get control values of Z for comparison
C     --------------------------------------

      open (16,file='cont.io',form='unformatted')
         DO NT=1,NTRAJC
            read(16) ((ZCONT(IW,JW,NT),IW=1,IKTX),JW=1,IKTY)
         ENDDO
      close(16)

C     Get the background state
C     ------------------------ 

      CALL BACKGROUND
      print*, 'Tout va bien (2)'
      DO IW=1,IKTX
      DO JW=1,IKTY
         ZO(IW,JW)= Zb(IW,JW,NSTOP) 
      END DO
      END DO

      DO IKX=1,IKTX
      DO IKY=1,IKTY
           ZG(IKX,IKY)   = ZO(IKX,IKY)
           ZGM1(IKX,IKY) = ZO(IKX,IKY)
      ENDDO
      ENDDO

C     The innovation vector 
C     ---------------------

      CALL H(ZO,SO,HX)
      DO IR = 1,2*N*N
        UWprime(IR) = dl_y(IR) - HX(IR) 
      END DO

C     The constant RHS 0.5 y'R-1y'
C     ----------------------------
  
      somme = 0.0
      DO IR = 1,2*N*N
         somme = somme + 0.5*UWprime(IR)**2/sigmao(IR)**2
      END DO
         print*, '== CTR3D_CG == Constant in the functional',somme


C      The initial residual b= B^T/2 HT R-1 y'
C      --------------------------------------

       DO IR = 1,2*N*N
         HX(IR) = UWprime(IR)/sigmao(IR)**2
       END DO

      CALL HT(HX,ZF,SO)
      CALL SQRTBT(ZF,ZR)

      IR = 0
      DO IW = 1,N
      DO JW=1,N
         IR = IR+1
         b(IR) = ZR(IW,JW)
      END DO
      END DO

C     Minimization
C     ------------


      open(23,file='mini_var.out',status='unknown')

      write(23,*) 'Constant term to be added to the functional =',somme
      call conjgrad(mv3dvar,KDIM,XX,b,0,x2,b2,two,
     &     zepsneg,zeps1,itermax,impres,
     &     nulout,kmode,mode,dl_vatra, imtra,
     &     preco,pmat0,npmat0,m0,ilm0,nilm0,wlm0,nwlm0,
     &     bfgsb,pmat1,npmat1,m1,ilm1,nilm1,wlm1,nwlm1,select,
     &     izs,zzsunused,dlds)

 
C     -------------------- FIN DES MINIMIZATIONS ----------------------
c     ----- TEST DU GRADIENT 
C      print*,'debut test du gradient'
C      KMIN    =   6
C      KMAX    =   13
C      DO KRANGE = KMIN,KMAX
C      DLGNORM = 0.
C      DLALPHA = 10.**(-KRANGE)
C      DO IKX=1,KDIM
C        DLGNORM = DLGNORM + GX(IKX)*GX(IKX)
C        XX(IKX) = XXO(IKX) - DLALPHA*GX(IKX)
C      ENDDO

C      call sim3d(KDIM,XX,JXF,GX)
C      ZTEST = (JXF-JX)/(-DLALPHA*DLGNORM)
      
C      print*,'ecritures test du gradient'
C      WRITE(*,99) KRANGE, DLALPHA, JX,JXF, ZTEST
C 99       FORMAT(3X,I3,4X,1PE12.6,4X,G12.6,4X,G12.6,4X,G12.6)
C      ENDDO
C      print*,'fin test du gradient'
C     ----------------------------------------------------------------


C     Analysis increment 
C     ------------------

      IR = 0
      DO IW = 1,N
      DO JW=1,N
         ZR(IW,JW)=XX(IR+1)
         IR=IR+1
      END DO
      END DO

      CALL SQRTB(ZR,ZF)

      print*, '*********ZR**********'

      CALL KR(ZF,ZR,KTX,KTY,IKTX,IKTY,N,N2,LWRK,
     .                  FF1,FF2,FF3,WORK,TRIGS,IFAX,ZI)

      open(16,file='increments_var_cg.dat',status='unknown')
           DO IW =1,N
           DO JW=1,N
              write(16,88) ZR(IW,JW)
           END DO
           END DO
      close(16)
   

C     Analysis state
C     --------------

      DO IKX=1,IKTX
      DO IKY=1,IKTY
         ZA(IKX,IKY) = ZF(IKX,IKY) + Zb(IKX,IKY,NSTOP)
         ZO(IKX,IKY) = ZA(IKX,IKY)
      END DO 
      END DO

      CALL KR(ZA,ZR,KTX,KTY,IKTX,IKTY,N,N2,LWRK,
     .                  FF1,FF2,FF3,WORK,TRIGS,IFAX,ZI)

      OPEN(17,file='analysis.dat',status='unknown')
           DO IW =1,N
           DO JW=1,N
              write(17,88) ZR(IW,JW)
           END DO 
           END DO 
      CLOSE(17)

      print*, 'Tout va bien (3)'

C     New guess
C     ---------
      open (15,file='newguess.io',status='unknown')
        write(15,102) ((ZA(IW,JW),IW=1,IKTX),JW=1,IKTY)
        write(15,102) ((SO(IW,JW),IW=1,IKTX),JW=1,IKTY)
      close(15)

C     Forecast
C     --------
      
      GRFLAG = 1 
      OBFLAG = 1
      TRFLAG = 1
      JXFLAG = 0
      TEFLAG = 0

      CALL MODDIR(JX)

      print*, 'Tout va bien (4)'

      IF(PTFLAG.EQ.1) CALL PATH(XX,XX1,KDIM)
      IF(RMFLAG.EQ.1) CALL RMSCON

      close(21)
      close(22)
      close(23)
      close(24)
      close(10)


 88   FORMAT(E12.4)
 102  FORMAT(8e13.7)

      print*, 'Tout va bien (fin)'

1000  CONTINUE
      STOP 
      END