C $Header: /u/gcmpack/MITgcm/pkg/bling/bling_airseaflux.F,v 1.5 2017/05/11 13:32:24 mmazloff Exp $
C $Name:  $

#include "BLING_OPTIONS.h"
#include "PTRACERS_OPTIONS.h"

CBOP
      subroutine BLING_AIRSEAFLUX( 
     I           PTR_DIC, PTR_ALK, PTR_O2, PTR_NO3, PTR_PO4, 
     O           SGDIC, SGO2, FluxO2, 
     I           bi, bj, imin, imax, jmin, jmax,
     I           myIter, myTime, myThid)

C     =================================================================
C     | subroutine bling_airseaflux
C     | o Calculate the carbon and oxygen air-sea flux terms
C     |   Adapted from pkg/dic/dic_surfforcing.F
C     | - Get atmospheric pCO2 value
C     |   Option 1: constant value, default 268.d-6, can be changed in 
C     |             data.bling
C     |   Option 2: read 2D field using EXF pkg
C     | - Update pCO2 and pH
C     =================================================================

      implicit none
      
C     === Global variables ===
#include "SIZE.h"
#include "DYNVARS.h"
#include "EEPARAMS.h"
#include "PARAMS.h"
#include "GRID.h"
#include "FFIELDS.h"
#ifdef ALLOW_EXF
# include "EXF_PARAM.h"
# include "EXF_FIELDS.h"
#endif
#include "BLING_VARS.h"
#ifdef ALLOW_AUTODIFF
# include "tamc.h"
#endif

C     === Routine arguments ===
C     myTime           :: current time
C     myIter           :: current timestep
C     myThid           :: thread Id. number
      _RL myTime
      INTEGER myIter
      INTEGER myThid
      INTEGER iMin, iMax, jMin, jMax, bi, bj
C     === Input ===
C     PTR_DIC          :: DIC tracer field
C     PTR_ALK          :: alkalinity tracer field
C     PTR_NO3          :: nitrate tracer field
C     PTR_PO4          :: phosphate tracer field
C     PTR_O2           :: oxygen tracer field
      _RL  PTR_DIC(1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr)
      _RL  PTR_ALK(1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr)
      _RL  PTR_NO3(1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr)
      _RL  PTR_PO4(1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr)
      _RL  PTR_O2 (1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr)
C     === Output ===
C     SGDIC            :: surface tendency of DIC due to air-sea exchange 
C     SGO2             :: surface tendency of O2 due to air-sea exchange 
C     FluxO2           :: air-sea flux of O2 
C     (FluxCO2 is a global variable) 
      _RL  SGDIC(1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL  SGO2(1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL  FluxO2(1-OLx:sNx+OLx,1-OLy:sNy+OLy)

#ifdef ALLOW_PTRACERS

C     === Local variables ===
C     i,j              :: Loop counters
      INTEGER i,j,klev
C Number of iterations for pCO2 solvers
      _RL co3dummy
      _RL Kwexch_Pre   (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
C Solubility relation coefficients
      _RL SchmidtNoDIC (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL pCO2sat      (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL Kwexch       (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL pisvel       (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
C local variables for carbon chem
      _RL surfalk      (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL surfphos     (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL surfsi       (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL surftemp     (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL surfsalt     (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL surfdic      (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
C o2 solubility relation coefficients
      _RL SchmidtNoO2  (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL O2sat        (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL O2sat_percent(1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL Kwexch_o2    (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL aTT
      _RL aTK
      _RL aTS
      _RL aTS2
      _RL aTS3
      _RL aTS4
      _RL aTS5
      _RL o2s
      _RL ttemp
      _RL stemp
      _RL oCnew
CEOP

C----------------------------------------------------------------------
C First, carbon
C----------------------------------------------------------------------
        klev=1
C determine inorganic carbon chem coefficients
        DO j=jmin,jmax
         DO i=imin,imax

             surfalk(i,j)  = PTR_ALK(i,j,1)
     &                          * maskC(i,j,1,bi,bj)
             surfphos(i,j) = PTR_PO4(i,j,1)
     &                          * maskC(i,j,1,bi,bj)

C FOR NON-INTERACTIVE Si
             surfsi(i,j)   = SILICA(i,j,bi,bj) * maskC(i,j,1,bi,bj)
             surftemp(i,j) = theta(i,j,1,bi,bj)
             surfsalt(i,j) = salt(i,j,1,bi,bj)
             surfdic(i,j)  = PTR_DIC(i,j,1)

          ENDDO
         ENDDO

         CALL CARBON_COEFFS(
     I                       surftemp,surfsalt,
     I                       bi,bj,iMin,iMax,jMin,jMax,myThid)

       DO j=jmin,jmax
        DO i=imin,imax
C Compute Kwexch_Pre which is re-used for flux of O2

c   Read EXF winds instead of value from file:
#ifdef ALLOW_EXF
              wind(i,j,bi,bj) = wspeed(i,j,bi,bj)
#endif

C Pre-compute part of exchange coefficient: pisvel*(1-fice)
C Schmidt number is accounted for later
              pisvel(i,j) = 0.337 _d 0 * wind(i,j,bi,bj)**2/3.6 _d 5
              Kwexch_Pre(i,j) = pisvel(i,j)
     &                              * (1. _d 0 - FIce(i,j,bi,bj))

        ENDDO
       ENDDO

c pCO2 solver...

CADJ STORE ph = comlev1, key = ikey_dynamics

C$TAF LOOP = parallel
       DO j=jmin,jmax
C$TAF LOOP = parallel
        DO i=imin,imax

          IF ( maskC(i,j,klev,bi,bj).NE.0. _d 0 ) THEN
            CALL CALC_PCO2_APPROX(
     I        surftemp(i,j),surfsalt(i,j),
     I        surfdic(i,j), surfphos(i,j),
     I        surfsi(i,j),surfalk(i,j),
     I        ak1(i,j,bi,bj),ak2(i,j,bi,bj),
     I        ak1p(i,j,bi,bj),ak2p(i,j,bi,bj),ak3p(i,j,bi,bj),
     I        aks(i,j,bi,bj),akb(i,j,bi,bj),akw(i,j,bi,bj),
     I        aksi(i,j,bi,bj),akf(i,j,bi,bj),
     I        ak0(i,j,bi,bj), fugf(i,j,bi,bj),
     I        ff(i,j,bi,bj),
     I        bt(i,j,bi,bj),st(i,j,bi,bj),ft(i,j,bi,bj),
     U        pH(i,j,klev,bi,bj),pCO2(i,j,bi,bj),co3dummy,
     I        i,j,klev,bi,bj,myIter,myThid )
          ELSE
            pCO2(i,j,bi,bj) = 0. _d 0
          ENDIF

        ENDDO
       ENDDO

       DO j=jmin,jmax
        DO i=imin,imax

          IF ( maskC(i,j,1,bi,bj).NE.0. _d 0 ) THEN
C calculate SCHMIDT NO. for CO2
              SchmidtNoDIC(i,j) =
     &            sca1
     &          + sca2 * theta(i,j,1,bi,bj)
     &          + sca3 * theta(i,j,1,bi,bj)*theta(i,j,1,bi,bj)
     &          + sca4 * theta(i,j,1,bi,bj)*theta(i,j,1,bi,bj)
     &                *theta(i,j,1,bi,bj)
c make sure Schmidt number is not negative (will happen if temp>39C)
             SchmidtNoDIC(i,j)=max(1.0 _d -2, SchmidtNoDIC(i,j))

C First determine local saturation pCO2
#ifdef USE_EXFCO2
              pCO2sat(i,j) = apco2(i,j,bi,bj) 
#else
              pCO2sat(i,j) = bling_pCO2
#endif

c Correct for atmospheric pressure
#ifdef USE_EXF_ATMPRES
C Atm pressure in N/m2, convert to bars
              pCO2sat(i,j) = pCO2sat(i,j)*(apressure(i,j,bi,bj)*0.00001)
#else
              pCO2sat(i,j) = pCO2sat(i,j)*AtmosP(i,j,bi,bj)
#endif

C then account for Schmidt number
              Kwexch(i,j) = Kwexch_Pre(i,j)
     &                    / sqrt(SchmidtNoDIC(i,j)/660.0 _d 0)

C Calculate flux in terms of DIC units using K0, solubility
c Flux = kw*rho*(ff*pCO2atm-k0*FugFac*pCO2ocean)
               FluxCO2(i,j,bi,bj) =
     &          Kwexch(i,j)*(
     &            ff(i,j,bi,bj)*pCO2sat(i,j) -
     &            pCO2(i,j,bi,bj)*fugf(i,j,bi,bj)
     &            *ak0(i,j,bi,bj) )
     &
          ELSE
              FluxCO2(i,j,bi,bj) = 0. _d 0
          ENDIF
          
C convert flux (mol kg-1 m s-1) to (mol m-2 s-1)
          FluxCO2(i,j,bi,bj) = FluxCO2(i,j,bi,bj)/permil

          ENDDO
         ENDDO

C update tendency
         DO j=jmin,jmax
          DO i=imin,imax
           SGDIC(i,j)= recip_drF(1)*recip_hFacC(i,j,1,bi,bj)
     &              *FluxCO2(i,j,bi,bj)
          ENDDO
         ENDDO

C----------------------------------------------------------------------
C Now oxygen
C----------------------------------------------------------------------

C calculate SCHMIDT NO. for O2
        DO j=jmin,jmax
          DO i=imin,imax
            IF (maskC(i,j,1,bi,bj).NE.0.) THEN
              ttemp = theta(i,j,1,bi,bj)
              stemp = salt(i,j,1,bi,bj)

              SchmidtNoO2(i,j) =
     &            sox1
     &          + sox2 * ttemp
     &          + sox3 * ttemp*ttemp
     &          + sox4 * ttemp*ttemp*ttemp

C Determine surface flux of O2
C exchange coeff accounting for ice cover and Schmidt no.
C Kwexch_Pre= pisvel*(1-fice): previously computed above

              Kwexch_o2(i,j) = Kwexch_Pre(i,j)
     &                    / sqrt(SchmidtNoO2(i,j)/660.0 _d 0)

C determine saturation O2
C using Garcia and Gordon (1992), L&O (mistake in original ?)
              aTT  = 298.15 _d 0 -ttemp
              aTK  = 273.15 _d 0 +ttemp
              aTS  = log(aTT/aTK)
              aTS2 = aTS*aTS
              aTS3 = aTS2*aTS
              aTS4 = aTS3*aTS
              aTS5 = aTS4*aTS

              oCnew  = oA0 + oA1*aTS + oA2*aTS2 + oA3*aTS3 +
     &            oA4*aTS4 + oA5*aTS5
     &          + stemp*(oB0 + oB1*aTS + oB2*aTS2 + oB3*aTS3)
     &          + oC0*(stemp*stemp)

              o2s = EXP(oCnew)

c Convert from ml/l to mol/m^3
              O2sat(i,j) = o2s/22391.6 _d 0 * 1. _d 3

cav
              O2sat_percent(i,j) = PTR_O2(i,j,1)/O2sat(i,j)*100

C Determine flux, inc. correction for local atmos surface pressure
#ifdef USE_EXF_ATMPRES
C Atm pressure in N/m2, convert to bars
              FluxO2(i,j) = Kwexch_o2(i,j)*(
     &                     (apressure(i,j,bi,bj)*0.00001)
     &                      *O2sat(i,j) - PTR_O2(i,j,1) )
#else
              FluxO2(i,j) = Kwexch_o2(i,j)*
     &                     (AtmosP(i,j,bi,bj)*O2sat(i,j)
     &                      - PTR_O2(i,j,1))
#endif
            ELSE
              FluxO2(i,j) = 0. _d 0
            ENDIF

          ENDDO
        ENDDO

C update surface tendencies
        DO j=jmin,jmax
          DO i=imin,imax
           SGO2(i,j)= FluxO2(i,j)
     &         *recip_drF(1) * recip_hFacC(i,j,1,bi,bj)
          ENDDO
        ENDDO

        _EXCH_XY_RL( pCO2, mythid)
        _EXCH_XYZ_RL( pH, mythid)

#ifdef ALLOW_DIAGNOSTICS
      IF ( useDiagnostics ) THEN
        CALL DIAGNOSTICS_FILL(O2sat_percent,'BLGO2SAT',0,1,2,bi,bj,
     &       myThid)
      ENDIF
#endif /* ALLOW_DIAGNOSTICS */

#endif /* ALLOW_PTRACER */

        RETURN
        END