C $Header: /u/gcmpack/MITgcm/pkg/seaice/advect.F,v 1.30 2014/10/20 03:20:57 gforget Exp $ C $Name: $ #include "SEAICE_OPTIONS.h" #ifdef ALLOW_AUTODIFF # include "AUTODIFF_OPTIONS.h" #endif CBOP C !ROUTINE: ADVECT C !INTERFACE: SUBROUTINE ADVECT( I UI, VI, U fld, O fldNm1, I iceMsk, myThid ) C !DESCRIPTION: \bv C *==========================================================* C | S/R ADVECT C | o Calculate advection and diffusion C | and update the input ice-field C *==========================================================* C \ev C !USES: IMPLICIT NONE C == Global variables === #include "SIZE.h" #include "EEPARAMS.h" #include "PARAMS.h" #include "GRID.h" #include "SEAICE_SIZE.h" #include "SEAICE_PARAMS.h" #ifdef ALLOW_AUTODIFF_TAMC # include "tamc.h" #endif C !INPUT/OUTPUT PARAMETERS: C == Routine arguments == C UI, VI :: ice velocity components C fld :: input and updated ice-field C fldNm1 :: copy of the input ice-field C iceMsk :: Ocean/Land mask C myThid :: my Thread Id. number _RL UI (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL VI (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL fld (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL fldNm1 (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL iceMsk (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) INTEGER myThid CEOP C !LOCAL VARIABLES: C == Local variables == C i,j,k,bi,bj :: Loop counters INTEGER i, j, bi, bj INTEGER k _RL DELTT _RL DIFFA (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL tmpFld (1-OLx:sNx+OLx,1-OLy:sNy+OLy,nSx,nSy) _RL afx (1-OLx:sNx+OLx,1-OLy:sNy+OLy) _RL afy (1-OLx:sNx+OLx,1-OLy:sNy+OLy) DELTT=SEAICE_deltaTtherm C save fld from previous time step DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx fldNm1(i,j,bi,bj) = fld(i,j,bi,bj) ENDDO ENDDO ENDDO ENDDO DO k=1,2 cph IF ( k .EQ. 1 ) THEN C Prediction step cph DO bj=myByLo(myThid),myByHi(myThid) cph DO bi=myBxLo(myThid),myBxHi(myThid) cph DO j=1-OLy,sNy+OLy cph DO i=1-OLx,sNx+OLx cph tmpFld(i,j,bi,bj) = fld(i,j,bi,bj) cph ENDDO cph ENDDO cph ENDDO cph ENDDO cph ELSE C Backward Euler correction step DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx cph for k=1 this is same as tmpFld = fld tmpFld(i,j,bi,bj)=HALF*(fld(i,j,bi,bj) & +fldNm1(i,j,bi,bj)) ENDDO ENDDO ENDDO ENDDO cph ENDIF #ifdef ALLOW_AUTODIFF_TAMC cphCADJ STORE fld = comlev1, key = ikey_dynamics cphCADJ STORE fldNm1 = comlev1, key = ikey_dynamics cphCADJ STORE tmpFld = comlev1, key = ikey_dynamics DO J=1-Oly,sNy+Oly DO I=1-Olx,sNx+Olx afx(i,j) = 0. _d 0 afy(i,j) = 0. _d 0 ENDDO ENDDO #endif /* ALLOW_AUTODIFF_TAMC */ C NOW GO THROUGH STANDARD CONSERVATIVE ADVECTION IF ( .NOT. SEAICEuseFluxForm ) THEN DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) DO j=0,sNy+1 DO i=0,sNx+1 CML This formulation gives the same result as the original code on a CML lat-lon-grid, but may not be accurate on irregular grids fld(i,j,bi,bj)=fldNm1(i,j,bi,bj) & -DELTT*( & ( tmpFld(i ,j ,bi,bj)+tmpFld(i+1,j ,bi,bj)) & * UI(i+1,j, bi,bj) - & ( tmpFld(i ,j ,bi,bj)+tmpFld(i-1,j ,bi,bj)) & * UI(i ,j, bi,bj) )*maskInC(i,j,bi,bj) & *(HALF * _recip_dxF(i,j,bi,bj)) & -DELTT*( & ( tmpFld(i ,j ,bi,bj)+tmpFld(i ,j+1,bi,bj)) & * VI(i ,j+1, bi,bj) & * _dxG(i ,j+1,bi,bj) - & ( tmpFld(i ,j ,bi,bj)+tmpFld(i ,j-1,bi,bj)) & * VI(i ,j , bi,bj) & * _dxG(i,j,bi,bj))*maskInC(i,j,bi,bj) & *(HALF * _recip_dyF(i,j,bi,bj) * _recip_dxF(i,j,bi,bj)) ENDDO ENDDO ENDDO ENDDO ELSE C-- Use flux form for MITgcm compliance, unfortunately changes results DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) C-- first compute fluxes across cell faces DO j=1,sNy+1 DO i=1,sNx+1 afx(i,j) = _dyG(i,j,bi,bj) * UI(i,j,bi,bj) & * 0.5 _d 0 * (tmpFld(i,j,bi,bj)+tmpFld(i-1,j,bi,bj)) afy(i,j) = _dxG(i,j,bi,bj) * VI(i,j,bi,bj) & * 0.5 _d 0 * (tmpFld(i,j,bi,bj)+tmpFld(i,j-1,bi,bj)) ENDDO ENDDO DO j=1,sNy DO i=1,sNx fld(i,j,bi,bj)=fldNm1(i,j,bi,bj) & -DELTT * ( & afx(i+1,j) - afx(i,j) & + afy(i,j+1) - afy(i,j) & )*recip_rA(i,j,bi,bj)*maskInC(i,j,bi,bj) ENDDO ENDDO ENDDO ENDDO ENDIF CALL EXCH_XY_RL( fld, myThid ) ENDDO IF ( DIFF1.GT.0. _d 0 ) THEN C NOW DO DIFFUSION C make a working copy of field from last time step DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx tmpFld(i,j,bi,bj) = fldNm1(i,j,bi,bj) ENDDO ENDDO ENDDO ENDDO C NOW CALCULATE DIFFUSION COEF ROUGHLY C 1rst pass: compute changes due to harmonic diffusion and add it to ice-field DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx DIFFA(i,j,bi,bj) = MIN( _dxF(i,j,bi,bj), _dyF(i,j,bi,bj) ) ENDDO ENDDO ENDDO ENDDO C- Compute laplacian of ice-field; return result in same array CALL DIFFUS( tmpFld, DIFFA, iceMsk, myThid ) DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx fld(i,j,bi,bj) = ( fld(i,j,bi,bj) & +tmpFld(i,j,bi,bj)*DIFF1*DELTT & )*iceMsk(i,j,bi,bj) ENDDO ENDDO ENDDO ENDDO c IF ( useBiHarmonic ) THEN C 2nd pass: compute changes due to biharmonic diffusion and add it to ice-field _EXCH_XY_RL( tmpFld, myThid ) C use some strange quadratic form for the second time around DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx #ifdef ALLOW_AUTODIFF_TAMC C to avoid recomputations when there was a k loop; not needed anymore c DIFFA(i,j,bi,bj) = MIN( _dxF(i,j,bi,bj), _dyF(i,j,bi,bj) ) #endif DIFFA(i,j,bi,bj) = - DIFFA(i,j,bi,bj)*DIFFA(i,j,bi,bj) ENDDO ENDDO ENDDO ENDDO C- Compute bilaplacian (laplacian of laplacian); return result in same array CALL DIFFUS( tmpFld, DIFFA, iceMsk, myThid ) DO bj=myByLo(myThid),myByHi(myThid) DO bi=myBxLo(myThid),myBxHi(myThid) DO j=1-OLy,sNy+OLy DO i=1-OLx,sNx+OLx fld(i,j,bi,bj) = ( fld(i,j,bi,bj) & +tmpFld(i,j,bi,bj)*DIFF1*DELTT & )*iceMsk(i,j,bi,bj) ENDDO ENDDO ENDDO ENDDO C-- end biharmonic block c ENDIF C-- end DIFF1 > 0 block ENDIF RETURN END