c

C.... file name GXBUOYSO.F              140206
C**** SUBROUTINE GXBUOY  is called from group 13 of GREX3, and is
C     entered only when the patch name begins with the characters 'BUOY'.
C
C.... The coding provided here presumes that CO in the relevant COVAL
C     statement is FIXFLUX, and that the VAL is:
C     GRND1, or (what is equivalent) DENSITY,     (ISC = 13)
C     GRND2, or (what is equivalent) DENDIFF,     (ISC = 14)
C     GRND3, or (what is equivalent) BOUSS,       (ISC = 15)
C     GRND4, or (what is equivalent) LINBC.       (ISC = 16)
C
C     The arguments BFC, CARTES and PARAB are logicals in the SATELLITE,
C     signifying, when set to T, the body-fitted coordinate, rectangular
C     cartesian coordinate and parabolic flow respectively.
C
C.... The following library cases make use of it:
C     213,P108-P112,740-743(bfctst)                 (VAL=GRND1)
C     122,125,136,137,278,251-254,256,279           (VAL=GRND3),
C     975                                           (VAL=GRND4).
C
      SUBROUTINE GXBUOY(BFC,CARTES,PARAB,DEN1,DEN2)
      INCLUDE 'farray'
      INCLUDE 'grdloc'
      INCLUDE 'satgrd'
      INCLUDE 'grdear'
      INCLUDE 'grdbfc'
      INCLUDE 'prpcmn'
      COMMON/IDATA/NX,NY,IFL2(118) /LDATA/LDFL1(7),XCYCLE,LDFL2(76)
     1      /RDATA/RDAT1(10),XULAST,RDAT2(67),DVO1DT,DVO2DT,RDAT3(5)
     1      /GENL/ LGN1(51),SOLIDM,SOLIDN,LGN3(7)
     1      /GENI/ NXNY,IGNI1(8),NFM,IGFIL(39),ITEM1,ITEM2,IGFIL2(4),
     1             IPRPS,IFIL1(4)
     1      /FNDRI/IDF(11),IJPW(6),IJPS(6),IDSG(6),IDR(6),JDR(6),KDR(6)
     1      /NAMFN/NAMFUN,NAMSUB
      COMMON/PASQLF/ITPRO,PASQBUOY,BUOSSG,MOLEN
      LOGICAL PASQBUOY,BUOSSG
      INTEGER DEN1,DEN2
      LOGICAL BFC,CARTES,PARAB,FLUID1,QNE,XCYCLE,LDFL1,LDFL2,SLD,
     1        TESTSOL,LGN1,SOLIDM,SOLIDN,LGN3,GRN,dbbuoy
      CHARACTER DIRCTN, NAMFUN*6, NAMSUB*6
C
      dbbuoy=.false.
      if(dbbuoy) then
        write(14,*) 'gxbuoy entered for '
        call writ2i('indvar  ',indvar,'isc     ',isc)
        call writ3r('buoya   ',buoya,'buoyb   ',buoyb,'buoyc   ',buoyc)
        call writ2r('buoyd   ',buoyd,'buoye   ',buoye)
      endif
      NAMSUB = 'GXBUOY'
      IF(INDVAR.LT.5) THEN
c.... which velocity?
c                                             U1 or U2
        DIRCTN = 'E'
        BUOABC=BUOYA
        IPLPHI=NY
        IPLSLD=NY
        TESTSOL=SOLIDM
      ELSEIF(INDVAR.LT.7) THEN
c                                             V1 or V2
        DIRCTN = 'N'
        BUOABC=BUOYB
        IPLPHI=1
        IPLSLD=1
        TESTSOL=SOLIDM
      ELSE
c                                             W1 or W2
        DIRCTN = 'H'
        BUOABC=BUOYC
        IPLPHI=NFM
        IPLSLD=NXNY
        TESTSOL=SOLIDM.OR.SOLIDN
      ENDIF
      if(dbbuoy) then
        call writ40('direction is '//dirctn)
      endif
c
      IF(ISC.LT.16) THEN
        if(dbbuoy) then
          call writ40('in gxbuoyso for value')
          call writ2l('bfc     ',bfc,'cartes  ',cartes)
        endif
C---------------------------------------- VAL=DENSITY, DENSDIFF or BOUSS
C.... Resolve gravity vector into local resolute direction; BUOYA,
C     BUOYB and BUOYC signify the resolutes of the acceleration
C     due to gravity in the cartesian coordinate direction XC,
C     YC and ZC.
!!MH-start
        IF(BFC.AND..NOT.GCV) THEN
C---------------------------------------------------------------- BFC=T
          CALL BFCBUO
C....          BFCBUO sets:
C              val = easp2*buoya + easp3*buoyb + easp4*buoyb ,
C                    where the easp's are the relevant direction cosines
       ELSEIF(GCV.AND.BFC)THEN
        CALL BUOPAT
C
         RETURN
!!MH-end
        ELSEIF(CARTES) THEN
C----------------------------------------------------- BFC=F & CARTES=T
c.... fn1(y,a)                 y = a
          CALL FN1(VAL,BUOABC)
C------------------------------------------- BFC=F & CARTES=F, ie POLAR
        ELSEIF(INDVAR.GT.6) THEN
C          BUOYC is the acceleration due to gravity in the z-direction
          CALL FN1(VAL,BUOYC)
        ELSEIF(QNE(BUOYB,0.0).OR.QNE(BUOYA,0.0)) THEN
C.... The following sequence assumes that gravity is aligned with x=0,
C     so that only BUOYB ( the y-direction cartesian component of
C     the gravity vector ) is relevant.
          IF(INDVAR.LT.5) THEN
C.... The u-direction source contains:  buoya*cos(xg) - buoyb*sin(xg)
            L0XG  = L0F(LXXG)
            L0VAL = L0F(VAL)
            IXLAST= NX-1
            IF(XCYCLE) IXLAST= NX
            PI=4*ATAN(1.0)
            DO 10 IX= 1,IXLAST
              ANGLE1= F(L0XG+IX)
              IF(IX.EQ.NX) THEN
                ANGLE2= F(L0XG+1)
                IF(ANGLE1.GT.PI) ANGLE2=ANGLE2+2*PI
              ELSE
                ANGLE2= F(L0XG+IX+1)
              ENDIF
              ANGLE = 0.5*(ANGLE1+ANGLE2)
              SOURCE= COS(ANGLE)*BUOYA - SIN(ANGLE)*BUOYB
              IPLUS = (IX-1)*NY
              DO 10 IY= 1+IPLUS,NY+IPLUS
                F(L0VAL+IY)= SOURCE
  10        CONTINUE
          ELSE
C.... The v-direction source contains:  buoya*sin(xg) + buoyb*cos(xg)
            L0XG2= L0F(XG2D)
            L0VAL = L0F(VAL)
            DO 20 IX= 1,NX
              DO 20 IY= 1,NY
                I= IY+(IX-1)*NY
                ANGLE= F(L0XG2+I)
                F(L0VAL+I)= BUOYA*SIN(ANGLE) + BUOYB*COS(ANGLE)
  20        CONTINUE
          ENDIF
        ELSE
c....                       set val to zero if buoya and buoyb are zero
          CALL FN1(VAL,0.0)
        ENDIF
        if(dbbuoy) call prn('val1',val)
        if(dbbuoy) call prn('ld9 ',ld9)
        IF(ISC.EQ.14) THEN
C.... 'Phasem' force = (rho - refrho) * grav ---- VAL=DENSDIFF (ie GRND2)
          IF(ITPRO==0.OR.ITPRO==4) THEN  ! uniform reference density
C     FN69(Y,X,A,B)             Y = Y * (A + B/X)
c.... LD9 is the block-location index of the correctly-staggered density,
c     therefore no further staggering is needed below
c
c....        Note that, apart from zeroing in solids, all has now been
c            done for VAL = DENSITY and VAL = DENSDIFF,
c            The other two options require staggering.
c.... note that the do loop provides better accuracy than FN69
            L0VAL= L0F(VAL)
            L0D9 = L0F(LD9)
            DO I=1,NXNY
              F(L0VAL+I) = F(L0VAL+I)*( F(L0D9+I) - BUOYD ) / F(L0D9+I)
            ENDDO
cccc          CALL FN69(VAL,LD9,1.0,-BUOYD)
          ELSE   ! reference density varies with height
            CALL GXBLIN
          ENDIF
          if(dbbuoy) call prn('val2',val)
        endif
      ELSE
C....                                    ISC=16: for VAL=LINBC (ie GRND4)
C.... Value set to a linear function of variables IBUOYB and IBUOYC
        CALL FNAV(EASP2,IBUOYB,DIRCTN)
        CALL FNAV(EASP3,IBUOYC,DIRCTN)
        CALL FN10(VAL,EASP2,EASP3,BUOYA,BUOYB,BUOYC)
        if(dbbuoy) call prn('val3',val)
      ENDIF
C----------------------------------------------------------------------
C---- VAL= BOUSS  (ie GRND3)
      IF(ISC.EQ.15) THEN
C.... 'Phasem' force = rho * grav * (exco   ) * (Tref - T1)
C....             OR   rho * grav * (exco/cp) * (href - h1)
C.... Preliminaries
C....                                fn27: y = y / x
        if(dbbuoy) call writ40('boussinesq option')
        IF(ITPRO>0 .AND. ITPRO/= 4) THEN  ! Pasquill Reference temperature varies with height
           CALL GXBLIN
        ELSE        ! uniform reference density
          IF(FLUID1(INDVAR)) THEN
            DVDT12= DVO1DT
            ITHMEX= THRME1
            IF(SOLVE(ITEM1)) THEN
              ITORH= ITEM1
            ELSE
              ITORH= H1
C.... Divide Val by Cp when enthalpy is solved
              CALL FN27(VAL,LCP1)
            ENDIF
          ELSE
            DVDT12= DVO2DT
            ITHMEX= THRME2
            IF(SOLVE(ITEM2)) THEN
              ITORH= ITEM2
            ELSE
              ITORH= H2
C.... Divide Val by Cp when enthalpy is solved
              CALL FN27(VAL,LCP2)
            ENDIF
          ENDIF
C.... Put staggered T or H in EASP2
          IF((INDVAR.LT.7.OR..NOT.PARAB)) THEN
            CALL FNAV(EASP2,ITORH,DIRCTN)
          ELSE
            CALL FN0(EASP2,ITORH)
          ENDIF
          if(dbbuoy) then
            call writ40('staggered t or h')
            call prn('tem1',itorh)
            call prn('easp2',easp2)
          endif
C.... Multiply gravity by Exco * (Tref - T1) or Exco * (Href - H)
          IF(IPRPS.NE.0 .OR. GRN(DVDT12)) THEN
C.... Variable expansion coefficient is set in INDPRP and put into
C     the LDVO1 storage
            CALL INDPRP(ITHMEX,0)
            if(dbbuoy) call writ1i('idvo1   ',idvo1)
            if(dbbuoy) call prn('dvo1',idvo1)
C....                                fn85: y = y * x1 * (A - x2)
            CALL FN85(VAL, IDVO1, EASP2, BUOYE)
 
            if(dbbuoy) call prn('vall',val)
          ELSE
C....                                fn46: y = y * (A + B * x1)
            CALL FN46(VAL, EASP2, BUOYE*DVDT12, -DVDT12)
          ENDIF
        ENDIF
      ENDIF
C.... Set VAL to zero in solids
      IF(TESTSOL) THEN
        L0VAL= L0F(VAL)
        DO 30 IX= IXF,IXL
          IADD= (IX-1)*NY
          DO 30 IY= IYF,IYL
            I= IY+IADD
            IF(SLD(I)) THEN
              F(L0VAL+I)= 0.0
            ELSE
              IF(SLD(I+IPLSLD)) F(L0VAL+I)= 0.0
            ENDIF
  30    CONTINUE
      ENDIF
      NAMSUB= 'gxbuoy'
      if(dbbuoy) write(14,*) 'leaving gxbuoy '
      END