C $Header: /u/gcmpack/MITgcm/pkg/sbo/sbo_calc.F,v 1.17 2014/05/30 17:10:15 jmc Exp $ C $Name: $ #include "SBO_OPTIONS.h" #ifdef ALLOW_SEAICE # include "SEAICE_OPTIONS.h" #endif CBOP C !ROUTINE: SBO_CALC C !INTERFACE: ========================================================== SUBROUTINE SBO_CALC( myTime, myIter, myThid ) C !DESCRIPTION: \bv C *==========================================================* C | SUBROUTINE SBO_CALC | C | o Do SBO diagnostic output. | C *==========================================================* C | NOTE: The following subtleties are ignored for time | C | being but may need revisiting at some point in time. | C | 1) The model is volume-preserving and Boussinesq so | C | quantities like oceanic mass need to be interpreted | C | with some care. We remove spurious mass variations | C | using the Greatbatch correction. Real freshwater | C | fluxes retained in mass load. | C | 2) The sea surface height variable etaN might lag other | C | prognostic variables by half a time step. This lag | C | is ignored in SBO computations. | C | 3) OAM due to currents assumes constant density | C | (=rhoConst), rms differences using variable density | C | is less than 1%, assuming rhoConst is a good measure | C | of the actual mean density | C | 4) Seaice motion added to OAMC. Seaice mass is in OAMP | C | and COM. Net freshwater flux is between atmosphere | C | and liquid ocean plus seaice. I.e. changes in seaice | C | mass due to melt/freeze with liquid ocean do not | C | change net freshwater flux. | C *==========================================================* C======================================================================= C C Based on ftp://euler.jpl.nasa.gov/sbo/software/calc_sbo2.f C Written by Richard Gross (Richard.Gross@jpl.nasa.gov) C Reference C Gross, R. S., F. O. Bryan, Y. Chao, J. O. Dickey, S. L. Marcus, C R. M. Ponte, and R. Tokmakian, The IERS Special Bureau for the C Oceans, in IERS Technical Note on the IERS Global Geophysical C Fluids Center, edited by B. Chao, in press, Observatoire de Paris, C Paris, France, 2002. C C June 10, 2001: Modified for online computations in MIT GCM UV C by Dimitris Menemenlis (Menemenlis@jpl.nasa.gov) C Jan 7, 2014: Modified for real freshwater flux and coordinates other C than spherical polar by Katy Quinn (kquinn@aer.com) C C Purpose C calc_sbo calculates the core products of the IERS Special Bureau C for the Oceans including oceanic mass, center-of-mass, and angular C momentum. C C======================================================================= C \ev C !USES: =============================================================== IMPLICIT NONE C === Global variables === #include "SIZE.h" #include "EEPARAMS.h" #include "PARAMS.h" #include "GRID.h" #include "DYNVARS.h" #include "FFIELDS.h" #include "SBO.h" #ifdef ALLOW_SEAICE # include "SEAICE_SIZE.h" # include "SEAICE.h" #endif C !INPUT PARAMETERS: =================================================== C == Routine arguments == C myTime :: Current time of simulation ( s ) C myIter :: Iteration number C myThid :: Number of this instance of SBO_CALC _RL myTime INTEGER myIter, myThid #ifdef ALLOW_SBO C !LOCAL VARIABLES: ==================================================== C bi, bj :: array indices C i :: index over longitude grid points C j :: index over latitude grid points C k :: index over layers C lat :: latitude of grid point (radians) C lon :: longitude of grid point (radians) C darea :: element of surface area (m**2) C dvolume :: element of volume (m**3) C ae :: mean radius of Earth (m) (PREM value) C sbo_omega :: mean angular velocity of Earth (rad/s) C UE,VN :: geographic (east,north) ocean velocities at cell centers (m/s) C UEice,VNice :: geographic (east,north) seaice velocities at cell centers (m/s) C Mload :: total mass load (kg/m**2) C GCload :: mass load for Greatbatch correction (kg/m**2) C FWLoad :: real freshwater flux mass load (kg/m**2) integer bi, bj, i, j, k _RL lat, lon, darea, dvolume _RL ae, sbo_omega PARAMETER ( ae = 6.3710 _d 6 ) PARAMETER ( sbo_omega = 7.292115 _d -5 ) _RL UE(1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr,nSx,nSy) _RL VN(1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr,nSx,nSy) _RL UEice(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL VNice(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL Mload(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL GCload, FWload C Tiled global sums _RL tile_FWload(nSx,nSy) _RL tile_sboarea(nSx,nSy) _RL tile_GCload(nSx,nSy) _RL tile_mass(nSx,nSy) _RL tile_xcom(nSx,nSy) _RL tile_ycom(nSx,nSy) _RL tile_zcom(nSx,nSy) _RL tile_xoamc(nSx,nSy) _RL tile_yoamc(nSx,nSy) _RL tile_zoamc(nSx,nSy) _RL tile_xoamp(nSx,nSy) _RL tile_yoamp(nSx,nSy) _RL tile_zoamp(nSx,nSy) _RL tile_xoamc_si(nSx,nSy) _RL tile_yoamc_si(nSx,nSy) _RL tile_zoamc_si(nSx,nSy) _RL tile_mass_si(nSx,nSy) _RL tile_mass_fw(nSx,nSy) _RL tile_xcom_fw(nSx,nSy) _RL tile_ycom_fw(nSx,nSy) _RL tile_zcom_fw(nSx,nSy) _RL tile_xoamp_fw(nSx,nSy) _RL tile_yoamp_fw(nSx,nSy) _RL tile_zoamp_fw(nSx,nSy) _RL tile_mass_gc (nSx,nSy) C Pre-computed cos(lat), sin(lat), cos(lon), sin(lon) _RL COSlat(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL SINlat(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL COSlon(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL SINlon(1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) CEOP C Initialize variables to be computed--------------------------------- C- note: only done once (by master thread) for var in common block _BEGIN_MASTER(myThid) xoamc = 0.0 yoamc = 0.0 zoamc = 0.0 xoamp = 0.0 yoamp = 0.0 zoamp = 0.0 mass = 0.0 xcom = 0.0 ycom = 0.0 zcom = 0.0 sboarea = 0.0 xoamc_si = 0.0 yoamc_si = 0.0 zoamc_si = 0.0 mass_si = 0.0 xoamp_fw = 0.0 yoamp_fw = 0.0 zoamp_fw = 0.0 mass_fw = 0.0 xcom_fw = 0.0 ycom_fw = 0.0 zcom_fw = 0.0 mass_gc = 0.0 _END_MASTER(myThid) C Get geographic (East,North) velocities------------------------------ CALL ROTATE_UV2EN_RL( U uVel, vVel, U UE, VN, I .TRUE., .TRUE., .FALSE., Nr, mythid ) #ifdef ALLOW_SEAICE IF ( useSEAICE ) THEN CALL ROTATE_UV2EN_RL( U UICE, VICE, U UEice, VNice, I .TRUE., .TRUE., .FALSE., 1, mythid ) ELSE #else /* ALLOW_SEAICE */ IF ( .TRUE. ) THEN #endif /* ALLOW_SEAICE */ DO bj = myByLo(myThid), myByHi(myThid) DO bi = myBxLo(myThid), myBxHi(myThid) DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx UEice(i,j,bi,bj) = 0. VNice(i,j,bi,bj) = 0. ENDDO ENDDO ENDDO ENDDO ENDIF C Calculate mass load------------------------------------------------- C Calculate mass load (Mload), Greatbatch correction for C spurious mass but spatial mean freshwater flux retained. C Mload *needs* to be total mass (for center of mass), so add C back missing time invariant term: -R_low*rhoConst c Calculate freshwater load C Calculate Greatbatch correction load over global ocean volume c Note: no halo regions in i,j loops, do not want to double book sums FWload = 0.0 GCload = 0.0 DO bj = myByLo(myThid), myByHi(myThid) DO bi = myBxLo(myThid), myBxHi(myThid) tile_FWload(bi,bj) = 0.0 tile_GCload(bi,bj) = 0.0 tile_sboarea(bi,bj) = 0.0 DO j = 1, sNy DO i = 1, sNx darea = rA(i,j,bi,bj)*maskC(i,j,1,bi,bj) tile_sboarea(bi,bj) = tile_sboarea(bi,bj) + darea tile_FWload(bi,bj) = tile_FWload(bi,bj) + & rhoConst*etaN(i,j,bi,bj)*darea + & sIceLoad(i,j,bi,bj)*darea DO k = 1, Nr dvolume = rA(i,j,bi,bj)*drF(k)*hFacC(i,j,k,bi,bj) tile_GCload(bi,bj) = tile_GCload(bi,bj) + & rhoInSitu(i,j,k,bi,bj) * dvolume ENDDO ENDDO ENDDO ENDDO ENDDO CALL GLOBAL_SUM_TILE_RL( tile_FWload , FWload , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_sboarea , sboarea , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_GCload , GCload , myThid ) FWload = FWload/sboarea GCload = -1.0 * GCload/sboarea c Total mass load with freshwater flux DO bj = myByLo(myThid), myByHi(myThid) DO bi = myBxLo(myThid), myBxHi(myThid) DO j = 1-OLy, sNy+OLy DO i = 1-OLx, sNx+OLx Mload(i,j,bi,bj) = rhoConst*etaN(i,j,bi,bj) + & sIceLoad(i,j,bi,bj) + & GCload - R_low(i,j,bi,bj)*rhoConst DO k = 1, Nr Mload(i,j,bi,bj) = Mload(i,j,bi,bj) + & rhoInSitu(i,j,k,bi,bj)*drF(k)*hFacC(i,j,k,bi,bj) ENDDO ENDDO ENDDO ENDDO ENDDO c Pre-compute cos(lat), sin(lat), cos(lon), sin(lon) DO bj = myByLo(myThid), myByHi(myThid) DO bi = myBxLo(myThid), myBxHi(myThid) DO j = 1-OLy, sNy+OLy DO i = 1-OLx, sNx+OLx lat = yC(i,j,bi,bj) * deg2rad lon = xC(i,j,bi,bj) * deg2rad COSlat(i,j,bi,bj) = COS(lat) SINlat(i,j,bi,bj) = SIN(lat) COSlon(i,j,bi,bj) = COS(lon) SINlon(i,j,bi,bj) = SIN(lon) ENDDO ENDDO ENDDO ENDDO C Main loops---------------------------------------------------------- C loop over all grid points, accumulating mass, com, oam C Note: no halo regions in i,j loops, do not want to double book sums DO bj = myByLo(myThid), myByHi(myThid) DO bi = myBxLo(myThid), myBxHi(myThid) C Initialize tile sums--------------------------------- tile_xoamc(bi,bj) = 0.0 tile_yoamc(bi,bj) = 0.0 tile_zoamc(bi,bj) = 0.0 tile_xoamp(bi,bj) = 0.0 tile_yoamp(bi,bj) = 0.0 tile_zoamp(bi,bj) = 0.0 tile_mass(bi,bj) = 0.0 tile_xcom(bi,bj) = 0.0 tile_ycom(bi,bj) = 0.0 tile_zcom(bi,bj) = 0.0 tile_xoamc_si(bi,bj) = 0.0 tile_yoamc_si(bi,bj) = 0.0 tile_zoamc_si(bi,bj) = 0.0 tile_mass_si(bi,bj) = 0.0 tile_xoamp_fw(bi,bj) = 0.0 tile_yoamp_fw(bi,bj) = 0.0 tile_zoamp_fw(bi,bj) = 0.0 tile_mass_fw(bi,bj) = 0.0 tile_xcom_fw(bi,bj) = 0.0 tile_ycom_fw(bi,bj) = 0.0 tile_zcom_fw(bi,bj) = 0.0 tile_mass_gc(bi,bj) = 0.0 DO j = 1, sNy DO i = 1, sNx IF ( maskC(i,j,1,bi,bj) .NE. 0. ) THEN C horizontal area darea = rA(i,j,bi,bj)*maskC(i,j,1,bi,bj) C accumulate mass of oceans, Greatbatch correction, seaice tile_mass(bi,bj) = tile_mass(bi,bj) + & Mload(i,j,bi,bj)*darea tile_mass_gc(bi,bj) = tile_mass_gc(bi,bj) + & GCload*darea tile_mass_si(bi,bj) = tile_mass_si(bi,bj) + & sIceLoad(i,j,bi,bj)*darea C accumulate center-of-mass of oceans (need to divide by total mass at end) tile_xcom(bi,bj) = tile_xcom(bi,bj) + & Mload(i,j,bi,bj)*COSlat(i,j,bi,bj)*COSlon(i,j,bi,bj) & * ae * darea tile_ycom(bi,bj) = tile_ycom(bi,bj) + & Mload(i,j,bi,bj)*COSlat(i,j,bi,bj)*SINlon(i,j,bi,bj) & * ae * darea tile_zcom(bi,bj) = tile_zcom(bi,bj) + & Mload(i,j,bi,bj)*SINlat(i,j,bi,bj) & * ae * darea C accumulate oceanic angular momentum due to currents (need depth integral too) C Note: depth integral goes from k=1,Nr. hFacC takes care of R_low and etaN (as per JMC) DO k = 1, Nr dvolume = rA(i,j,bi,bj)*drF(k) & * maskC(i,j,k,bi,bj)*hFacC(i,j,k,bi,bj) tile_xoamc(bi,bj) = tile_xoamc(bi,bj) + & ( VN(i,j,k,bi,bj)*SINlon(i,j,bi,bj) - & UE(i,j,k,bi,bj)* & SINlat(i,j,bi,bj)*COSlon(i,j,bi,bj) ) & * rhoConst * ae * dvolume tile_yoamc(bi,bj) = tile_yoamc(bi,bj) + & (-VN(i,j,k,bi,bj)*COSlon(i,j,bi,bj) - & UE(i,j,k,bi,bj)* & SINlat(i,j,bi,bj)*SINlon(i,j,bi,bj) ) & * rhoConst * ae * dvolume tile_zoamc(bi,bj) = tile_zoamc(bi,bj) + & UE(i,j,k,bi,bj)*COSlat(i,j,bi,bj) & * rhoConst * ae * dvolume ENDDO C accumulate sea angular momentum due to motion (one layer, so no depth integral needed) tile_xoamc_si(bi,bj) = tile_xoamc_si(bi,bj) + & ( VNice(i,j,bi,bj)*SINlon(i,j,bi,bj) - & UEice(i,j,bi,bj)* & SINlat(i,j,bi,bj)*COSlon(i,j,bi,bj) ) & * sIceLoad(i,j,bi,bj) * ae * darea tile_yoamc_si(bi,bj) = tile_yoamc_si(bi,bj) + & (-VNice(i,j,bi,bj)*COSlon(i,j,bi,bj) - & UEice(i,j,bi,bj)* & SINlat(i,j,bi,bj)*SINlon(i,j,bi,bj) ) & * sIceLoad(i,j,bi,bj) * ae * darea tile_zoamc_si(bi,bj) = tile_zoamc_si(bi,bj) + & UEice(i,j,bi,bj)*COSlat(i,j,bi,bj) & * sIceLoad(i,j,bi,bj) * ae * darea C accumulate oceanic angular momentum due to pressure tile_xoamp(bi,bj) = tile_xoamp(bi,bj) - & SINlat(i,j,bi,bj)*COSlat(i,j,bi,bj)*COSlon(i,j,bi,bj) & * sbo_omega * Mload(i,j,bi,bj) * ae*ae * darea tile_yoamp(bi,bj) = tile_yoamp(bi,bj) - & SINlat(i,j,bi,bj)*COSlat(i,j,bi,bj)*SINlon(i,j,bi,bj) & * sbo_omega * Mload(i,j,bi,bj) * ae*ae * darea tile_zoamp(bi,bj) = tile_zoamp(bi,bj) + & COSlat(i,j,bi,bj) * COSlat(i,j,bi,bj) & * sbo_omega * Mload(i,j,bi,bj) * ae*ae * darea C accumulate mass of real freshwater flux tile_mass_fw(bi,bj) = tile_mass_fw(bi,bj) + & FWload * darea C accumulate center-of-mass of real freshwater flux (need to divide by total FW mass at end) tile_xcom_fw(bi,bj) = tile_xcom_fw(bi,bj) + & FWload * COSlat(i,j,bi,bj) * COSlon(i,j,bi,bj) & * ae * darea tile_ycom_fw(bi,bj) = tile_ycom_fw(bi,bj) + & FWload * COSlat(i,j,bi,bj) * SINlon(i,j,bi,bj) & * ae * darea tile_zcom_fw(bi,bj) = tile_zcom_fw(bi,bj) + & FWload * SINlat(i,j,bi,bj) & * ae * darea C accumulate oceanic angular momentum due to real freshwater flux tile_xoamp_fw(bi,bj) = tile_xoamp_fw(bi,bj) - & SINlat(i,j,bi,bj)*COSlat(i,j,bi,bj)*COSlon(i,j,bi,bj) & * sbo_omega * FWload * ae*ae * darea tile_yoamp_fw(bi,bj) = tile_yoamp_fw(bi,bj) - & SINlat(i,j,bi,bj)*COSlat(i,j,bi,bj)*SINlon(i,j,bi,bj) & * sbo_omega * FWload * ae*ae * darea tile_zoamp_fw(bi,bj) = tile_zoamp_fw(bi,bj) + & COSlat(i,j,bi,bj) * COSlat(i,j,bi,bj) & * sbo_omega * FWload * ae*ae * darea C end if over ocean ENDIF C end loop over i,j ENDDO ENDDO C end loop over bi,bj ENDDO ENDDO C sum all global values across model tiles CALL GLOBAL_SUM_TILE_RL( tile_mass , mass , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_xcom , xcom , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_ycom , ycom , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_zcom , zcom , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_xoamc , xoamc , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_yoamc , yoamc , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_zoamc , zoamc , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_xoamp , xoamp , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_yoamp , yoamp , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_zoamp , zoamp , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_xoamc_si , xoamc_si , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_yoamc_si , yoamc_si , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_zoamc_si , zoamc_si , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_mass_si , mass_si , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_mass_fw , mass_fw , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_xcom_fw , xcom_fw , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_ycom_fw , ycom_fw , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_zcom_fw , zcom_fw , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_xoamp_fw , xoamp_fw , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_yoamp_fw , yoamp_fw , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_zoamp_fw , zoamp_fw , myThid ) CALL GLOBAL_SUM_TILE_RL( tile_mass_gc , mass_gc , myThid ) C finish calculating center-of-mass of oceans C- note: only master thread updates/modifies var in common block _BEGIN_MASTER(myThid) IF ( mass.NE.zeroRL ) THEN xcom = xcom / mass ycom = ycom / mass zcom = zcom / mass ENDIF IF ( mass_fw.NE.zeroRL ) THEN xcom_fw = xcom_fw / mass_fw ycom_fw = ycom_fw / mass_fw zcom_fw = zcom_fw / mass_fw ENDIF C Add seaice OAMC to total OAMC xoamc = xoamc + xoamc_si yoamc = yoamc + yoamc_si zoamc = zoamc + zoamc_si _END_MASTER(myThid) #endif /* ALLOW_SBO */ RETURN END