C $Header: /u/gcmpack/MITgcm/pkg/bulk_force/bulkf_forcing.F,v 1.14 2013/04/23 16:31:50 jmc Exp $ C $Name: $ #include "BULK_FORCE_OPTIONS.h" CBOP C !ROUTINE: BULKF_FORCING C !INTERFACE: SUBROUTINE BULKF_FORCING( I myTime, myIter, myThid ) C !DESCRIPTION: \bv C *==========================================================* C | SUBROUTINE BULKF_FORCING C *==========================================================* C \ev C o Get the surface fluxes used to force ocean model C Output: C ------ C ustress, vstress :: wind stress C qnet :: net heat flux C empmr :: freshwater flux C --------- C C Input: C ------ C uwind, vwind :: mean wind speed (m/s) at height hu (m) C Tair :: mean air temperature (K) at height ht (m) C Qair :: mean air humidity (kg/kg) at height hq (m) C theta(k=1) :: sea surface temperature (K) C rain :: precipitation C runoff :: river(ice) runoff C C ================================================================== C SUBROUTINE bulkf_forcing C ================================================================== C !USES: IMPLICIT NONE C == global variables == #include "EEPARAMS.h" #include "SIZE.h" #include "PARAMS.h" #include "DYNVARS.h" #include "GRID.h" #include "FFIELDS.h" #include "BULKF_PARAMS.h" #include "BULKF.h" #include "BULKF_INT.h" #include "BULKF_TAVE.h" C !INPUT/OUTPUT PARAMETERS: C == routine arguments == _RL myTime INTEGER myIter INTEGER myThid CEOP #ifdef ALLOW_BULK_FORCE C == Local variables == INTEGER bi,bj INTEGER i,j INTEGER ks, iceornot _RL df0dT, hfl, evp, dEvdT #ifdef ALLOW_FORMULA_AIM _RL SHF(1), EVPloc(1), SLRU(1) _RL dEvp(1), sFlx(0:2) #endif C- surface level index: ks = 1 C- Compute surface fluxes over ice-free ocean only: iceornot = 0 DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) DO j = 1-OLy,sNy+OLy DO i = 1-OLx,sNx+OLx IF ( maskC(i,j,ks,bi,bj).NE.0. _d 0 ) THEN #ifdef ALLOW_FORMULA_AIM IF ( useFluxFormula_AIM ) THEN CALL BULKF_FORMULA_AIM( I theta(i,j,ks,bi,bj), flwdwn(i,j,bi,bj), I thAir(i,j,bi,bj), Tair(i,j,bi,bj), I Qair(i,j,bi,bj), wspeed(i,j,bi,bj), O SHF, EVPloc, SLRU, O dEvp, sFlx, I iceornot, myThid ) flwup(i,j,bi,bj)= ocean_emissivity*SLRU(1) C- reverse sign (AIM convention -> BULKF convention): fsh(i,j,bi,bj) = -SHF(1) flh(i,j,bi,bj) = -Lvap*EVPloc(1) C- Convert from g/m2/s to m/s evap(i,j,bi,bj) = EVPloc(1) * 1. _d -3 / rhoFW dEvdT = dEvp(1) * 1. _d -3 df0dT = sFlx(2) ELSEIF ( blk_nIter.EQ.0 ) THEN #else /* ALLOW_FORMULA_AIM */ IF ( blk_nIter.EQ.0 ) THEN #endif /* ALLOW_FORMULA_AIM */ CALL BULKF_FORMULA_LANL( I uwind(i,j,bi,bj),vwind(i,j,bi,bj),wspeed(i,j,bi,bj), I Tair(i,j,bi,bj), Qair(i,j,bi,bj), I cloud(i,j,bi,bj),theta(i,j,ks,bi,bj), O flwup(i,j,bi,bj), flh(i,j,bi,bj), O fsh(i,j,bi,bj), df0dT, O ustress(i,j,bi,bj), vstress(i,j,bi,bj), O evp, savssq(i,j,bi,bj), dEvdT, I iceornot, myThid ) C Note that the LANL flux conventions are opposite C of what they are in the model. C- Convert from kg/m2/s to m/s evap(i,j,bi,bj) = evp/rhoFW ELSE CALL BULKF_FORMULA_LAY( I uwind(i,j,bi,bj), vwind(i,j,bi,bj), I wspeed(i,j,bi,bj), Tair(i,j,bi,bj), I Qair(i,j,bi,bj), theta(i,j,ks,bi,bj), O flwup(i,j,bi,bj), flh(i,j,bi,bj), O fsh(i,j,bi,bj), df0dT, O ustress(i,j,bi,bj), vstress(i,j,bi,bj), O evp, savssq(i,j,bi,bj), dEvdT, I iceornot, i,j,bi,bj,myThid ) C- Convert from kg/m2/s to m/s evap(i,j,bi,bj) = evp/rhoFW ENDIF C- use down long wave data flwupnet(i,j,bi,bj)=flwup(i,j,bi,bj)-flwdwn(i,j,bi,bj) C- using down solar, need to have water albedo -- .1 fswnet(i,j,bi,bj) = solar(i,j,bi,bj) & *( 1. _d 0 - ocean_albedo ) ElSE ustress(i,j,bi,bj) = 0. _d 0 vstress(i,j,bi,bj) = 0. _d 0 fsh(i,j,bi,bj) = 0. _d 0 flh(i,j,bi,bj) = 0. _d 0 flwup(i,j,bi,bj) = 0. _d 0 evap(i,j,bi,bj) = 0. _d 0 fswnet(i,j,bi,bj) = 0. _d 0 savssq(i,j,bi,bj) = 0. _d 0 ENDIF ENDDO ENDDO IF ( calcWindStress ) THEN C- move wind stresses to u and v points DO j = 1-OLy,sNy+OLy DO i = 1-OLx+1,sNx+OLx fu(i,j,bi,bj) = maskW(i,j,1,bi,bj) & *(ustress(i,j,bi,bj)+ustress(i-1,j,bi,bj))*0.5 _d 0 ENDDO ENDDO DO j = 1-OLy+1,sNy+OLy DO i = 1-OLx,sNx+OLx fv(i,j,bi,bj) = maskS(i,j,1,bi,bj) & *(vstress(i,j,bi,bj)+vstress(i,j-1,bi,bj))*0.5 _d 0 ENDDO ENDDO ENDIF C- Add all contributions. DO j = 1-OLy,sNy+OLy DO i = 1-OLx,sNx+OLx IF ( maskC(i,j,ks,bi,bj).NE.0. _d 0 ) THEN C- Net downward surface heat flux : hfl = 0. _d 0 hfl = hfl + fsh(i,j,bi,bj) hfl = hfl + flh(i,j,bi,bj) hfl = hfl - flwupnet(i,j,bi,bj) hfl = hfl + fswnet(i,j,bi,bj) C- Heat flux: Qnet(i,j,bi,bj) = -hfl Qsw (i,j,bi,bj) = -fswnet(i,j,bi,bj) #ifdef COUPLE_MODEL dFdT(i,j,bi,bj) = df0dT #endif C- Fresh-water flux from Precipitation and Evaporation. EmPmR(i,j,bi,bj) = (evap(i,j,bi,bj)-rain(i,j,bi,bj) & - runoff(i,j,bi,bj))*rhoConstFresh C---- cheating: now done in S/R BULKF_FLUX_ADJUST, over ice-free ocean only c Qnet(i,j,bi,bj) = Qnetch(i,j,bi,bj) c EmPmR(i,j,bi,bj) = EmPch(i,j,bi,bj) C---- ELSE Qnet(i,j,bi,bj) = 0. _d 0 Qsw (i,j,bi,bj) = 0. _d 0 EmPmR(i,j,bi,bj)= 0. _d 0 #ifdef COUPLE_MODEL dFdT(i,j,bi,bj) = 0. _d 0 #endif ENDIF ENDDO ENDDO IF ( temp_EvPrRn .NE. UNSET_RL ) THEN C-- Account for energy content of Precip + RunOff & Evap. Assumes: C 1) Rain has same temp as Air C 2) Snow has no heat capacity (consistent with seaice & thsice pkgs) C 3) No distinction between sea-water Cp and fresh-water Cp C 4) Run-Off comes at the temp of surface water (with same Cp) C 5) Evap is released to the Atmos @ surf-temp (=SST); should be using C the water-vapor heat capacity here and consistently in Bulk-Formulae; C Could also be put directly into Latent Heat flux. c IF ( SnowFile .NE. ' ' ) THEN C-- Melt snow (if provided) into the ocean and account for rain-temp c DO j = 1-OLy,sNy+OLy c DO i = 1-OLx,sNx+OLx c Qnet(i,j,bi,bj) = Qnet(i,j,bi,bj) c & + Lfresh*snowPrecip(i,j,bi,bj)*rhoConstFresh c & - HeatCapacity_Cp c & *( Tair(i,j,bi,bj) - Tf0kel - temp_EvPrRn ) c & *( rain(i,j,bi,bj)- snowPrecip(i,j,bi,bj) ) c & *rhoConstFresh c ENDDO c ENDDO c ELSE C-- Make snow (according to Air Temp) and melt it in the ocean C note: here we just use the same criteria as over seaice but would be C better to consider a higher altitude air temp, e.g., 850.mb DO j = 1-OLy,sNy+OLy DO i = 1-OLx,sNx+OLx IF ( Tair(i,j,bi,bj).LE.Tf0kel ) THEN Qnet(i,j,bi,bj) = Qnet(i,j,bi,bj) & + Lfresh*rain(i,j,bi,bj)*rhoConstFresh ELSE C-- Account for rain-temp Qnet(i,j,bi,bj) = Qnet(i,j,bi,bj) & - HeatCapacity_Cp & *( Tair(i,j,bi,bj) - Tf0kel - temp_EvPrRn ) & *rain(i,j,bi,bj)*rhoConstFresh ENDIF ENDDO ENDDO c ENDIF C-- Account for energy content of Evap and RunOff: DO j = 1-OLy,sNy+OLy DO i = 1-OLx,sNx+OLx c Qnet(i,j,bi,bj) = Qnet(i,j,bi,bj) c & + ( theta(i,j,ks,bi,bj) - temp_EvPrRn ) c & *( evap(i,j,bi,bj)*cpwv c & - runoff(i,j,bi,bj)*HeatCapacity_Cp c & )*rhoConstFresh Qnet(i,j,bi,bj) = Qnet(i,j,bi,bj) & + ( theta(i,j,ks,bi,bj) - temp_EvPrRn ) & *( evap(i,j,bi,bj) - runoff(i,j,bi,bj) ) & *HeatCapacity_Cp*rhoConstFresh Qnet(i,j,bi,bj) = Qnet(i,j,bi,bj)*maskC(i,j,ks,bi,bj) ENDDO ENDDO ENDIF IF ( blk_taveFreq.GT.0. _d 0 ) & CALL BULKF_AVE( bi, bj, myThid ) C-- end bi,bj loops ENDDO ENDDO C-- Update the tile edges. C jmc: Is it necessary ? c _EXCH_XY_RS(Qnet, myThid) c _EXCH_XY_RS(EmPmR, myThid) c CALL EXCH_UV_XY_RS(fu, fv, .TRUE., myThid) #endif /*ALLOW_BULK_FORCE*/ RETURN END