MODULE traadv_qck !!============================================================================== !! *** MODULE traadv_qck *** !! Ocean active tracers: horizontal & vertical advective trend !!============================================================================== !! History : 3.0 ! 2008-07 (G. Reffray) Original code !!---------------------------------------------------------------------- !!---------------------------------------------------------------------- !! tra_adv_qck : update the tracer trend with the horizontal advection !! trends using a 3rd order finite difference scheme !! tra_adv_qck_i : !! tra_adv_qck_j : !! tra_adv_cen2_k : 2nd centered scheme for the vertical advection !!---------------------------------------------------------------------- USE oce ! ocean dynamics and active tracers USE dom_oce ! ocean space and time domain USE trdmod ! ocean active tracers trends USE trdmod_oce ! ocean variables trends USE trabbl ! advective term in the BBL USE lib_mpp ! distribued memory computing USE lbclnk ! ocean lateral boundary condition (or mpp link) USE dynspg_oce ! surface pressure gradient variables USE in_out_manager ! I/O manager USE diaptr ! poleward transport diagnostics USE prtctl ! Print control IMPLICIT NONE PRIVATE PUBLIC tra_adv_qck ! routine called by step.F90 REAL(wp), DIMENSION(jpi,jpj) :: btr2 REAL(wp) :: r1_6 !! * Substitutions # include "domzgr_substitute.h90" # include "vectopt_loop_substitute.h90" !!---------------------------------------------------------------------- !! NEMO/OPA 3.2 , LOCEAN-IPSL (2009) !! $Id$ !! Software governed by the CeCILL licence (modipsl/doc/NEMO_CeCILL.txt) !!---------------------------------------------------------------------- CONTAINS SUBROUTINE tra_adv_qck( kt, pun, pvn, pwn ) !!---------------------------------------------------------------------- !! *** ROUTINE tra_adv_qck *** !! !! ** Purpose : Compute the now trend due to the advection of tracers !! and add it to the general trend of passive tracer equations. !! !! ** Method : The advection is evaluated by a third order scheme !! For a positive velocity u : u(i)>0 !! |--FU--|--FC--|--FD--|------| !! i-1 i i+1 i+2 !! !! For a negative velocity u : u(i)<0 !! |------|--FD--|--FC--|--FU--| !! i-1 i i+1 i+2 !! where FU is the second upwind point !! FD is the first douwning point !! FC is the central point (or the first upwind point) !! !! Flux(i) = u(i) * { 0.5(FC+FD) -0.5C(i)(FD-FC) -((1-C(i))/6)(FU+FD-2FC) } !! with C(i)=|u(i)|dx(i)/dt (=Courant number) !! !! dt = 2*rdtra and the scalar values are tb and sb !! !! On the vertical, the simple centered scheme used tn and sn !! !! The fluxes are bounded by the ULTIMATE limiter to !! guarantee the monotonicity of the solution and to !! prevent the appearance of spurious numerical oscillations !! !! ** Action : - update (ta,sa) with the now advective tracer trends !! - save the trends ('key_trdtra') !! !! ** Reference : Leonard (1979, 1991) !!---------------------------------------------------------------------- USE oce, ONLY : ztrdt => ua ! use ua as workspace USE oce, ONLY : ztrds => va ! use va as workspace !! INTEGER , INTENT(in) :: kt ! ocean time-step index REAL(wp), INTENT(in), DIMENSION(jpi,jpj,jpk) :: pun ! effective ocean velocity, u_component REAL(wp), INTENT(in), DIMENSION(jpi,jpj,jpk) :: pvn ! effective ocean velocity, v_component REAL(wp), INTENT(in), DIMENSION(jpi,jpj,jpk) :: pwn ! effective ocean velocity, w_component !! INTEGER :: ji, jj, jk ! dummy loop indices REAL(wp) :: z_hdivn_x, z_hdivn_y, z_hdivn ! temporary scalars REAL(wp) :: zbtr, z2 ! " " !!---------------------------------------------------------------------- IF( kt == nit000 ) THEN IF(lwp) WRITE(numout,*) IF(lwp) WRITE(numout,*) 'tra_adv_qck : 3rd order quickest advection scheme' IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~' IF(lwp) WRITE(numout,*) btr2(:,:) = 1. / ( e1t(:,:) * e2t(:,:) ) r1_6 = 1. / 6. ENDIF IF( neuler == 0 .AND. kt == nit000 ) THEN ; z2 = 1. ELSE ; z2 = 2. ENDIF ! I. The horizontal fluxes are computed with the QUICKEST + ULTIMATE scheme !--------------------------------------------------------------------------- CALL tra_adv_qck_i( pun, tb, tn, ta, ztrdt, z2) CALL tra_adv_qck_i( pun, sb, sn, sa, ztrds, z2) IF( l_trdtra ) CALL trd_mod(ztrdt, ztrds, jptra_trd_xad, 'TRA', kt) CALL tra_adv_qck_j( kt, pvn, tb, tn, ta, ztrdt, pht_adv, z2) CALL tra_adv_qck_j( kt, pvn, sb, sn, sa, ztrds, pst_adv, z2) IF( l_trdtra ) THEN CALL trd_mod(ztrdt, ztrds, jptra_trd_yad, 'TRA', kt) ! ztrdt(:,:,:) = ta(:,:,:) ! Save the horizontal up-to-date ta/sa trends ztrds(:,:,:) = sa(:,:,:) END IF IF(ln_ctl) CALL prt_ctl( tab3d_1=ta, clinfo1=' qck had - Ta: ', mask1=tmask, & & tab3d_2=sa, clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' ) ! II. The vertical fluxes are computed with the 2nd order centered scheme !------------------------------------------------------------------------- ! CALL tra_adv_cen2_k( pwn, tn, ta ) CALL tra_adv_cen2_k( pwn, sn, sa ) ! !Save the vertical advective trends for diagnostic ! ---------------------------------------------------- IF( l_trdtra ) THEN ! Recompute the vertical advection zta & zsa trends computed ! at the step 2. above in making the difference between the new ! trends and the previous one: ta()/sa - ztrdt()/ztrds() and substract ! the term tn()/sn()*hdivn() to recover the W gradz(T/S) trends DO jk = 1, jpkm1 DO jj = 2, jpjm1 DO ji = fs_2, fs_jpim1 ! vector opt. #if defined key_zco zbtr = btr2(ji,jj) z_hdivn_x = e2u(ji,jj)*pun(ji,jj,jk) - e2u(ji-1,jj)*pun(ji-1,jj,jk) z_hdivn_y = e1v(ji,jj)*pvn(ji,jj,jk) - e1v(ji,jj-1)*pvn(ji,jj-1,jk) #else zbtr = btr2(ji,jj) / fse3t(ji,jj,jk) z_hdivn_x = e2u(ji,jj)*fse3u(ji,jj,jk)*pun(ji,jj,jk) - e2u(ji-1,jj)*fse3u(ji-1,jj,jk)*pun(ji-1,jj,jk) z_hdivn_y = e1v(ji,jj)*fse3v(ji,jj,jk)*pvn(ji,jj,jk) - e1v(ji,jj-1)*fse3v(ji,jj-1,jk)*pvn(ji,jj-1,jk) #endif z_hdivn = (z_hdivn_x + z_hdivn_y) * zbtr ztrdt(ji,jj,jk) = ta(ji,jj,jk) - ztrdt(ji,jj,jk) - tn(ji,jj,jk) * z_hdivn ztrds(ji,jj,jk) = sa(ji,jj,jk) - ztrds(ji,jj,jk) - sn(ji,jj,jk) * z_hdivn END DO END DO END DO CALL trd_mod(ztrdt, ztrds, jptra_trd_zad, 'TRA', kt) ENDIF IF(ln_ctl) CALL prt_ctl( tab3d_1=ta, clinfo1=' qck zad - Ta: ', mask1=tmask, & & tab3d_2=sa, clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' ) ! END SUBROUTINE tra_adv_qck SUBROUTINE tra_adv_qck_i ( pun, tra, tran, traa, ztrdtra, z2 ) !!---------------------------------------------------------------------- !! !!---------------------------------------------------------------------- REAL, INTENT(in) :: z2 REAL(wp), INTENT(in) , DIMENSION(jpi,jpj,jpk) :: pun, tra, tran ! horizontal effective velocity REAL(wp), INTENT(out) , DIMENSION(jpi,jpj,jpk) :: ztrdtra REAL(wp), INTENT(inout), DIMENSION(jpi,jpj,jpk) :: traa ! INTEGER :: ji, jj, jk REAL(wp) :: za, zbtr, dir, dx, dt ! temporary scalars REAL(wp) :: z_hdivn_x REAL(wp), DIMENSION(jpi,jpj) :: zmask, zupst, zdwst, zc_cfl REAL(wp), DIMENSION(jpi,jpj) :: zfu, zfc, zfd, zfho, zmskl, zsc_e REAL(wp), DIMENSION(jpi,jpj,jpk) :: zflux !---------------------------------------------------------------------- zfu (:,jpj) = 0.e0 ; zfc (:,jpj) = 0.e0 zfd (:,jpj) = 0.e0 ; zc_cfl(:,jpj) = 0.e0 zsc_e (:,jpj) = 0.e0 ; zmskl (:,jpj) = 0.e0 zfho (:,jpj) = 0.e0 ! =============== DO jk = 1, jpkm1 ! Horizontal slab ! ! =============== !--- Computation of the ustream and downstream value of the tracer and the mask DO jj = 2, jpjm1 DO ji = 2, fs_jpim1 ! vector opt. ! Upstream in the x-direction for the tracer zupst(ji,jj)=tra(ji-1,jj,jk) ! Downstream in the x-direction for the tracer zdwst(ji,jj)=tra(ji+1,jj,jk) ! Mask at the T-points in the x-direction (mask=0 or mask=1) zmask(ji,jj)=tmask(ji-1,jj,jk)+tmask(ji,jj,jk)+tmask(ji+1,jj,jk)-2 END DO END DO ! !--- Lateral boundary conditions CALL lbc_lnk( zupst(:,:), 'T', 1. ) CALL lbc_lnk( zdwst(:,:), 'T', 1. ) CALL lbc_lnk( zmask(:,:), 'T', 1. ) ! ! Horizontal advective fluxes ! --------------------------- ! dt = z2 * rdttra(jk) !--- tracer flux at u-points DO jj = 1, jpjm1 DO ji = 1, jpi #if defined key_zco zsc_e(ji,jj) = e2u(ji,jj) #else zsc_e(ji,jj) = e2u(ji,jj) * fse3u(ji,jj,jk) #endif dir = 0.5 + sign(0.5,pun(ji,jj,jk)) ! if pun>0 : dir = 1 otherwise dir = 0 dx = dir * e1t(ji,jj) + (1-dir)* e1t(ji+1,jj) zc_cfl (ji,jj) = ABS(pun(ji,jj,jk))*dt/dx ! (00 : dir = 1 otherwise dir = 0 dx = dir * e2t(ji,jj) + (1-dir)* e2t(ji,jj+1) zc_cfl(ji,jj) = ABS(pvn(ji,jj,jk))*dt/dx ! (0= zcoef2(:,:) ) fho(:,:) = fc(:,:) ELSEWHERE zcoef3(:,:) = fu(:,:) + ( ( fc(:,:) - fu(:,:) )/MAX(fc_cfl(:,:),1.e-9) ) ! phi_REF WHERE ( zcoef1(:,:) >= 0.e0 ) fho(:,:) = MAX(fc(:,:),fho(:,:)) fho(:,:) = MIN(fho(:,:),MIN(zcoef3(:,:),fd(:,:))) ELSEWHERE fho(:,:) = MIN(fc(:,:),fho(:,:)) fho(:,:) = MAX(fho(:,:),MAX(zcoef3(:,:),fd(:,:))) ENDWHERE ENDWHERE ! END SUBROUTINE quickest !!====================================================================== END MODULE traadv_qck