SUBROUTINE CH_RDSBALOPER 1,2
C
*---------------------------------------------------------
#if defined (DOC)
*
**s/r ch_rdsbaloper - Read in balance operators spectral coefficients
*                     related to species
*
*Author  : Y.J. Rochon, ARQX/MSC April 2007
*
*Revision:
*
*    -------------------
*
* PURPOSE: Read in balance operators spectral coefficients
*          related to species
*
*          NOTES: 
*
*          1) See rdspptot.ftn for reference in constructing/reading file.
*
*          2) Providing of the correct covariances of the transformed variable
*             is the user's responsibility. Note that the NOMVAR of stored
*             covariances for the transformed and untransformed is assumed 
*             the same.
*
*             One option the user/originator has is to include
*             a covariance transformation in this routine instead of
*             reading new covariances for the transformed variable.
*           
*
*Arguments:
*
*   INPUT
*
*   OUTPUT  
*
*-----------------------------------------------------------
#endif
      IMPLICIT NONE
C
C     Global variables
C
#include "comdim.cdk"
#include "comlun.cdk"
#include "comchem.cdk"
#include "comstate.cdk"
#include "combalop.cdk"
#include "comspg.cdk"
#include "rpnstd.cdk"
C
C*    Local variables
C
      integer j,in1,in2,j1,ifound,ikey
      real*8 zbalop(nflev,nflev,nj)
      real*8 zbuffer(nj,nflev)
      logical sigtrans
C
      sigtrans=.TRUE.

      if (nbalop.eq.0) return
C
      WRITE(NULOUT,*) ' '
      WRITE(NULOUT,*) 'Enter CH_RDSBALOPER: NBALOP=',NBALOP
      WRITE(NULOUT,*) ' '                   
C 
      IF (NBALOP.GT.NBALNUM1.OR.NBALOP*NJ.GT.NBALNUM2.OR.
     &    NFLEV.GT.NBALNUM3) THEN
          WRITE(NULOUT,*) 'NBALOP,NBALOP*NJ,NFLEV =',
     &                     NBALOP,NBALOP*NJ,NFLEV
          CALL ABORT3D(NULOUT,'CH_RDSBALOPER: Dimension error!')
      END IF 
C
      open(unit=668,file='./unbalanced_stddev.asc',status='UNKNOWN')
      open(unit=667,file='./total_stddev.asc',status='UNKNOWN')

      DO J=1,NBALOP
C
         WRITE(NULOUT,*) 'J ',J
C
C        Identify index of source field (in GD)
C
         IFOUND=0
         IF (CBALOPSRC(J).eq.'UU') THEN
            IFOUND=NGPOSIT(NGUU)
         ELSE IF (CBALOPSRC(J).eq.'VV') THEN
            IFOUND=NGPOSIT(NGVV)
         ELSE IF (CBALOPSRC(J).eq.'GZ') THEN
            IFOUND=NGPOSIT(NGGZ)
         ELSE IF (CBALOPSRC(J).eq.'HU'.or.CBALOPSRC(J).eq.'LQ') THEN
            IFOUND=NGPOSIT(NGQ)
            CBALOPSRC(J)='LQ'
         ELSE IF (CBALOPSRC(J).eq.'TT') THEN
            IFOUND=NGPOSIT(NGTT)
         ELSE IF (CBALOPSRC(J).eq.'VV') THEN
            IFOUND=NGPOSIT(NGVV)
         ELSE IF (CBALOPSRC(J).eq.'P0') THEN
            IFOUND=NGPOSIT(NGPS) 
         ELSE IF (CBALOPSRC(J).eq.'TG') THEN
            IFOUND=NGPOSIT(NGTG)
         ELSE
            DO J1=1,NGCMT
               IF (CBALOPSRC(J).eq.CGCMT(J1)) THEN
                  IFOUND=NGPOSIT(NGTR(J1))
                  EXIT
               END IF 
            END DO   
         END IF   
         IF (IFOUND.GT.0) THEN
            NBALSRC(J)=IFOUND
            WRITE(NULOUT,*) 'CBALOPSRC(J),ILOC = ',CBALOPSRC(J),IFOUND
         ELSE
            WRITE(NULOUT,*) 'CBALOPSRC = ',CBALOPSRC(J)
            CALL ABORT3D(NULOUT,'CH_RDSBALOPER: SRC field not found!')        
         END IF
C
C        Identify index of destination field (in GD) 
C
         IFOUND=0
         IF (CBALOPDEST(J).eq.'UU') THEN
            IFOUND=NGPOSIT(NGUU)
         ELSE IF (CBALOPDEST(J).eq.'VV') THEN
            IFOUND=NGPOSIT(NGVV)
         ELSE IF (CBALOPDEST(J).eq.'GZ') THEN
            IFOUND=NGPOSIT(NGGZ)
         ELSE IF (CBALOPDEST(J).eq.'HU'.or.CBALOPDEST(J).eq.'LQ') THEN
            IFOUND=NGPOSIT(NGQ)
            CBALOPDEST(J)='LQ'
         ELSE IF (CBALOPDEST(J).eq.'TT') THEN
            IFOUND=NGPOSIT(NGTT)
         ELSE IF (CBALOPDEST(J).eq.'VV') THEN
            IFOUND=NGPOSIT(NGVV)
         ELSE IF (CBALOPDEST(J).eq.'P0') THEN
            IFOUND=NGPOSIT(NGPS)
         ELSE IF (CBALOPDEST(J).eq.'TG') THEN
            IFOUND=NGPOSIT(NGTG) 
         ELSE
            DO J1=1,NGCMT
               IF (CBALOPDEST(J).eq.CGCMT(J1)) THEN
                  IFOUND=NGPOSIT(NGTR(J1))
                  EXIT
               END IF
            END DO
         END IF
         IF (IFOUND.GT.0) THEN
            NBALDEST(J)=IFOUND
            WRITE(NULOUT,*) 'CBALOPDEST(J),ILOC = ',CBALOPDEST(J),IFOUND
         ELSE
            WRITE(NULOUT,*) 'CBALOPDEST = ',CBALOPDEST(J)            
            CALL ABORT3D(NULOUT,'CH_RDSBALOPER: Dest. field not found!')
         END IF 
C
C        Read and store any requested operator (input file name and
C        form of expected operator hardcoded by originator)
C
         CALL CH_RDBALOP(CBALOPFILE,CBALOPDEST(J),CBALOPETIK(J),
     &        in1,in2,zbalop,nj,nflev)
C
         nbali(J)=in1
         if ((in1.ne.1.and.in1.ne.nflev).or.in2.ne.nflev)
     &            CALL ABORT3D(NULOUT,'CH_RDSBALOPER: Dimension error!') 
C               
         balop(1:in1,1:in2,1+(j-1)*nj:j*nj)=
     &            zbalop(1:in1,1:in2,1:nj)
C
c        write(6,*) 'baloper ',balop(1,1+nflev/3,1+(j-1)*nj:j*nj)
C
C        Correspondindly modify std. dev. of unbalanced/destination field
C
         if (sigtrans) then
C
C           Identify location of fields in std. dev. arrays
C
            ifound=0
            if (CBALOPDEST(J).eq.'UU') then
               ifound=NSPOSIT(NSVOR)
            else if (CBALOPDEST(J).eq.'VV') then
               ifound=NSPOSIT(NSDIV)
            else if (CBALOPDEST(J).eq.'TT') then
               ifound=NSPOSIT(NSTT)
            else if (CBALOPDEST(J).eq.'LQ'.OR.CBALOPDEST(J).eq.'HU') then
               ifound=NSPOSIT(NSQ)
            else if (CBALOPDEST(J).eq.'GZ') then
               ifound=NSPOSIT(NSGZ)  
            else if (CBALOPDEST(J).eq.'P0') then
               ifound=NSPOSIT(NSPS)
            else if (CBALOPDEST(J).eq.'TG') then
               ifound=NSPOSIT(NSTG)
            else
               DO J1=1,NSCMT
                  IF (CBALOPDEST(J).eq.CSCMT(J1)) THEN
                     IFOUND=NSPOSIT(NSTR(J1))
                     EXIT
                  END IF
               END DO
            end if
            IF (IFOUND.GT.0) THEN
               in1=IFOUND
               WRITE(NULOUT,*) 'CBALOPDEST(J) sigma field index = ',IFOUND
             ELSE
               WRITE(NULOUT,*) 'CBALOPDEST = ',CBALOPDEST(J)
               CALL ABORT3D(NULOUT,'CH_RDSBALOPER: Dest. field not found!')
             END IF
C
            ifound=0
            if (CBALOPSRC(J).eq.'PP') then
               ifound=NSPOSIT(NSVOR) 
            else if (CBALOPSRC(J).eq.'UC') then
               ifound=NSPOSIT(NSDIV)
            else if (CBALOPSRC(J).eq.'UT') then
               ifound=NSPOSIT(NSTT)
            else if (CBALOPSRC(J).eq.'HU'.OR.CBALOPSRC(J).eq.'LQ') then
               ifound=NSPOSIT(NSQ)
            else if (CBALOPSRC(J).eq.'GZ') then
               ifound=NSPOSIT(NSGZ)
            else if (CBALOPSRC(J).eq.'P0') then
               ifound=NSPOSIT(NSPS)
            else if (CBALOPSRC(J).eq.'TG') then
               ifound=NSPOSIT(NSTG)
            else
               DO J1=1,NSCMT
                  IF (CBALOPSRC(J).eq.CSCMT(J1)) THEN
                     IFOUND=NSPOSIT(NSTR(J1))
                     EXIT
                  END IF   
               END DO   
            end if   
            IF (IFOUND.GT.0) THEN
               in2=IFOUND
               zbuffer=rgsig(1:nj,in2:in2+nflev-1)
               WRITE(NULOUT,*) 'CBALOPSRC(J) sigma field index = ',IFOUND 
             ELSE
               IKEY = VFSTLIR(ZBUFFER,nulbgst,INI,INJ,INK,-1
     &            ,'STDDEV',-1,-1,-1,' ',CBALOPSRC(J))
               if (ikey.gt.0) then
                 WRITE(NULOUT,*) 'CBALOPSRC(J) std. dev. found.'      
               else
                 WRITE(NULOUT,*) 'CBALOPSRC = ',CBALOPSRC(J)
                 CALL ABORT3D(NULOUT,'CH_RDSBALOPER: Dest. field not found!')
               end if
             END IF
C
C            Complete balance operator and apply std. dev. adjustment
C
c             write(nulout,*) 'Init. rgsig: ',rgsig(1:nj,in1+nflev/3)
C
             do j1=0, nflev-1
                 write(667, 400)(rgsig(in2,in1+j1),in2=nj,1,-1)
             enddo
             write(667,*)
C
             IF (NBALI(J).eq.1) THEN
C
C               Matrix operator: Does not include spatial correlation and
C               is a function only of latitude and vertical level.
C
C----           Correlation coefficients were provided. First, 
C               convert to decoupling (balance) operator.
C
                zbalop(1,1:nflev,1:nj)=zbalop(1,1:nflev,1:nj)*
     &              transpose(rgsig(1:nj,in1:in1+nflev-1))/
     &              transpose(zbuffer)
                balop(1,1:nflev,1+(j-1)*nj:j*nj)=
     &              zbalop(1,1:nflev,1:nj)
C
C----
                rgsig(1:nj,in1:in1+nflev-1)=
     &            sqrt(max(0.0001*rgsig(1:nj,in1:in1+nflev-1)**2,
     &                rgsig(1:nj,in1:in1+nflev-1)**2-
     &                (transpose(zbalop(1,1:nflev,1:nj))*zbuffer)**2))
C
             ELSE
C
C              Matrix operator: Includes vertical correlation and
C              is a function only of latitude and vertical level.
C
C              TBD
               
C
             END IF
C
             do j1=0, nflev-1
                 write(668, 400)(rgsig(in2,in1+j1),in2=nj,1,-1)
             enddo
             write(668,*)
C
c             write(nulout,*) 'balop:       ',zbalop(1,1+nflev/3,1:nj)
c             write(nulout,*) 'zbuffer:     ',zbuffer(1:nj,1+nflev/3)
c             write(nulout,*) 'final rgsig: ',rgsig(1:nj,in1+nflev/3)
C
         end if
C
      END DO
C
      WRITE(NULOUT,*) ' '                   
      WRITE(NULOUT,*) 'Exit CH_RDSBALOPER'
      WRITE(NULOUT,*) ' '
C
      close (unit=667,status='KEEP')
      close (unit=668,status='KEEP')
400   format(2x, 7(g11.5, 3x))
           

      return
      end