From ee6ce8c554140bc1070b32b9c3d63f8deee31abb Mon Sep 17 00:00:00 2001 From: Sibylle TECHENE <techenes@irene193.c-irene.tgcc.ccc.cea.fr> Date: Wed, 27 Jul 2022 12:35:39 +0200 Subject: [PATCH] reduce local memory usage for 2 halos #80 --- src/OCE/TRA/traadv.F90 | 13 +- src/OCE/TRA/traadv_cen.F90 | 338 ++++++++++++++++++++++++++++++++++++- src/OCE/TRA/traadv_mus.F90 | 220 +++++++++++++++++++++++- src/TOP/TRP/trcadv.F90 | 11 +- 4 files changed, 571 insertions(+), 11 deletions(-) diff --git a/src/OCE/TRA/traadv.F90 b/src/OCE/TRA/traadv.F90 index 190a6a7ad..924ee9331 100644 --- a/src/OCE/TRA/traadv.F90 +++ b/src/OCE/TRA/traadv.F90 @@ -10,6 +10,7 @@ MODULE traadv !! - ! 2014-12 (G. Madec) suppression of cross land advection option !! 3.6 ! 2015-06 (E. Clementi) Addition of Stokes drift in case of wave coupling !! 4.5 ! 2021-04 (G. Madec, S. Techene) add advective velocities as optional arguments + !! 4.5 ! 2022-06 (S. Techene, G, Madec) refactorization to reduce local memory usage !!---------------------------------------------------------------------- !!---------------------------------------------------------------------- @@ -178,7 +179,7 @@ CONTAINS ! !!gm ??? ! TEMP: [tiling] This copy-in not necessary after all lbc_lnks removed in the nn_hls = 2 case in tra_adv_fct - IF( l_diaptr ) CALL dia_ptr( kt, Kmm, zvv(A2D(0),:) ) ! diagnose the effective MSF + IF( l_diaptr ) CALL dia_ptr( kt, Kmm, zvv(A2D(nn_hls),:) ) ! diagnose the effective MSF !!gm ??? ! @@ -191,11 +192,19 @@ CONTAINS SELECT CASE ( nadv ) !== compute advection trend and add it to general trend ==! ! CASE ( np_CEN ) ! Centered scheme : 2nd / 4th order - CALL tra_adv_cen ( kt, nit000, 'TRA', zuu, zvv, zww, Kmm, pts, jpts, Krhs, nn_cen_h, nn_cen_v ) + IF( nn_hls == 1 ) THEN + CALL tra_adv_cen_hls1( kt, nit000, 'TRA', zuu, zvv, zww, Kmm, pts, jpts, Krhs, nn_cen_h, nn_cen_v ) + ELSE + CALL tra_adv_cen ( kt, nit000, 'TRA', zuu, zvv, zww, Kmm, pts, jpts, Krhs, nn_cen_h, nn_cen_v ) + ENDIF CASE ( np_FCT ) ! FCT scheme : 2nd / 4th order CALL tra_adv_fct ( kt, nit000, 'TRA', rDt, zuu, zvv, zww, Kbb, Kmm, pts, jpts, Krhs, nn_fct_h, nn_fct_v ) CASE ( np_MUS ) ! MUSCL + IF( nn_hls == 1 ) THEN + CALL tra_adv_mus_hls1( kt, nit000, 'TRA', rDt, zuu, zvv, zww, Kbb, Kmm, pts, jpts, Krhs, ln_mus_ups ) + ELSE CALL tra_adv_mus( kt, nit000, 'TRA', rDt, zuu, zvv, zww, Kbb, Kmm, pts, jpts, Krhs, ln_mus_ups ) + END IF CASE ( np_UBS ) ! UBS CALL tra_adv_ubs ( kt, nit000, 'TRA', rDt, zuu, zvv, zww, Kbb, Kmm, pts, jpts, Krhs, nn_ubs_v ) CASE ( np_QCK ) ! QUICKEST diff --git a/src/OCE/TRA/traadv_cen.F90 b/src/OCE/TRA/traadv_cen.F90 index 3351e1935..1666eee41 100644 --- a/src/OCE/TRA/traadv_cen.F90 +++ b/src/OCE/TRA/traadv_cen.F90 @@ -4,6 +4,7 @@ MODULE traadv_cen !! Ocean tracers: advective trend (2nd/4th order centered) !!====================================================================== !! History : 3.7 ! 2014-05 (G. Madec) original code + !! 4.5 ! 2022-06 (S. Techene, G, Madec) refactorization to reduce local memory usage !!---------------------------------------------------------------------- !!---------------------------------------------------------------------- @@ -29,7 +30,8 @@ MODULE traadv_cen IMPLICIT NONE PRIVATE - PUBLIC tra_adv_cen ! called by traadv.F90 + PUBLIC tra_adv_cen ! called by traadv.F90 + PUBLIC tra_adv_cen_hls1 ! called by traadv.F90 REAL(wp) :: r1_6 = 1._wp / 6._wp ! =1/6 @@ -47,7 +49,321 @@ MODULE traadv_cen !!---------------------------------------------------------------------- CONTAINS + SUBROUTINE tra_adv_cen_test( kt, kit000, cdtype, pU, pV, pW, & + & Kmm, pt, kjpt, Krhs, kn_cen_h, kn_cen_v ) + !!---------------------------------------------------------------------- + !! *** ROUTINE tra_adv_cen *** + !! + !! ** 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 2nd or 4th order scheme + !! using now fields (leap-frog scheme). + !! kn_cen_h = 2 ==>> 2nd order centered scheme on the horizontal + !! = 4 ==>> 4th order - - - - + !! kn_cen_v = 2 ==>> 2nd order centered scheme on the vertical + !! = 4 ==>> 4th order COMPACT scheme - - + !! + !! ** Action : - update pt(:,:,:,:,Krhs) with the now advective tracer trends + !! - send trends to trdtra module for further diagnostcs (l_trdtra=T) + !! - poleward advective heat and salt transport (l_diaptr=T) + !!---------------------------------------------------------------------- + INTEGER , INTENT(in ) :: kt ! ocean time-step index + INTEGER , INTENT(in ) :: Kmm, Krhs ! ocean time level indices + INTEGER , INTENT(in ) :: kit000 ! first time step index + CHARACTER(len=3) , INTENT(in ) :: cdtype ! =TRA or TRC (tracer indicator) + INTEGER , INTENT(in ) :: kjpt ! number of tracers + INTEGER , INTENT(in ) :: kn_cen_h ! =2/4 (2nd or 4th order scheme) + INTEGER , INTENT(in ) :: kn_cen_v ! =2/4 (2nd or 4th order scheme) + ! TEMP: [tiling] This can be A2D(nn_hls) after all lbc_lnks removed in the nn_hls = 2 case in tra_adv_fct + REAL(wp), DIMENSION(jpi,jpj,jpk ), INTENT(in ) :: pU, pV, pW ! 3 ocean volume flux components + REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt,jpt), INTENT(inout) :: pt ! tracers and RHS of tracer equation + ! + INTEGER :: ji, jj, jk, jn ! dummy loop indices + INTEGER :: ierr ! local integer + REAL(wp) :: zC2t_u, zC4t_u ! local scalars + REAL(wp) :: zC2t_v, zC4t_v ! - - + REAL(wp) :: zftw_kp1 + REAL(wp), DIMENSION(A2D(1)) :: zft_u, zft_v !, zft_w + REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: zdt_u, zdt_v + REAL(wp), DIMENSION(:,:,:) , ALLOCATABLE :: ztw + !!---------------------------------------------------------------------- + ! +#if defined key_loop_fusion + CALL tra_adv_cen_lf ( kt, nit000, cdtype, pU, pV, pW, Kmm, pt, kjpt, Krhs, kn_cen_h, kn_cen_v ) +#else + IF( .NOT. l_istiled .OR. ntile == 1 ) THEN ! Do only on the first tile + IF( kt == kit000 ) THEN + IF(lwp) WRITE(numout,*) + IF(lwp) WRITE(numout,*) 'tra_adv_cen : centered advection scheme on ', cdtype, ' order h/v =', kn_cen_h,'/', kn_cen_v + IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~ ' + ENDIF + ! ! set local switches + l_trd = .FALSE. + l_hst = .FALSE. + l_ptr = .FALSE. + IF( ( cdtype == 'TRA' .AND. l_trdtra ) .OR. ( cdtype == 'TRC' .AND. l_trdtrc ) ) l_trd = .TRUE. + IF( cdtype == 'TRA' .AND. ( iom_use( 'sophtadv' ) .OR. iom_use( 'sophtadv' ) ) ) l_ptr = .TRUE. + IF( cdtype == 'TRA' .AND. ( iom_use("uadv_heattr") .OR. iom_use("vadv_heattr") .OR. & + & iom_use("uadv_salttr") .OR. iom_use("vadv_salttr") ) ) l_hst = .TRUE. + ENDIF + ! + ! !* 2nd order centered + DO jn = 1, kjpt !== loop over the tracers ==! + ! + DO jk = 1, jpkm1 + ! + DO_2D( 1, 0, 1, 0 ) ! Horizontal fluxes at layer jk + zft_u(ji,jj) = 0.5_wp * pU(ji,jj,jk) * ( pt(ji,jj,jk,jn,Kmm) + pt(ji+1,jj ,jk,jn,Kmm) ) + zft_v(ji,jj) = 0.5_wp * pV(ji,jj,jk) * ( pt(ji,jj,jk,jn,Kmm) + pt(ji ,jj+1,jk,jn,Kmm) ) + END_2D + ! + DO_2D( 0, 0, 0, 0 ) ! Horizontal divergence of advective fluxes + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - ( zft_u(ji,jj) - zft_u(ji-1,jj ) & + & + zft_v(ji,jj) - zft_v(ji ,jj-1) ) * r1_e1e2t(ji,jj) & + & / e3t(ji,jj,jk,Kmm) + END_2D + END DO + ! +#define zft_w zft_u + IF( ln_linssh ) THEN !* top value (linear free surf. only as zwz is multiplied by wmask) + DO_2D( 0, 0, 0, 0 ) + zft_w(ji,jj) = pW(ji,jj,1) * pt(ji,jj,1,jn,Kmm) + END_2D + ELSE + DO_2D( 0, 0, 0, 0 ) + zft_w(ji,jj) = 0._wp + END_2D + ENDIF + DO jk = 1, jpk-2 + DO_2D( 0, 0, 0, 0 ) ! Vertical fluxes + zftw_kp1 = 0.5 * pW(ji,jj,jk+1) * ( pt(ji,jj,jk+1,jn,Kmm) + pt(ji,jj,jk,jn,Kmm) ) * wmask(ji,jj,jk+1) + ! + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - ( zft_w(ji,jj) - zftw_kp1 ) * r1_e1e2t(ji,jj) & + & / e3t(ji,jj,jk,Kmm) + zft_w(ji,jj) = zftw_kp1 + END_2D + END DO + jk = jpkm1 ! bottom vertical flux set to zero for all tracers + DO_2D( 0, 0, 0, 0 ) + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - zft_w(ji,jj) * r1_e1e2t(ji,jj) & + & / e3t(ji,jj,jk,Kmm) + END_2D + ! + END DO + ! + + ! +#undef zft_w + ! ! trend diagnostics +!!gm + !!st to be done with the whole rewritting of trd +!! trd routine arguments MUST be changed adding jk and zwx, zwy in 2D +!! IF( l_trd ) THEN +!! CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jptra_xad, zwx, pU, pt(:,:,:,jn,Kmm) ) +!! CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jptra_yad, zwy, pV, pt(:,:,:,jn,Kmm) ) +!! CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jptra_zad, zwz, pW, pt(:,:,:,jn,Kmm) ) +!! ENDIF +!! ! ! "Poleward" heat and salt transports +!! IF( l_ptr ) CALL dia_ptr_hst( jn, 'adv', zwy(:,:,:) ) +!! ! ! heat and salt transport +!! IF( l_hst ) CALL dia_ar5_hst( jn, 'adv', zwx(:,:,:), zwy(:,:,:) ) + ! + ! + ! +#endif + END SUBROUTINE tra_adv_cen_test + + SUBROUTINE tra_adv_cen( kt, kit000, cdtype, pU, pV, pW, & + & Kmm, pt, kjpt, Krhs, kn_cen_h, kn_cen_v ) + !!---------------------------------------------------------------------- + !! *** ROUTINE tra_adv_cen *** + !! + !! ** 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 2nd or 4th order scheme + !! using now fields (leap-frog scheme). + !! kn_cen_h = 2 ==>> 2nd order centered scheme on the horizontal + !! = 4 ==>> 4th order - - - - + !! kn_cen_v = 2 ==>> 2nd order centered scheme on the vertical + !! = 4 ==>> 4th order COMPACT scheme - - + !! + !! ** Action : - update pt(:,:,:,:,Krhs) with the now advective tracer trends + !! - send trends to trdtra module for further diagnostcs (l_trdtra=T) + !! - poleward advective heat and salt transport (l_diaptr=T) + !!---------------------------------------------------------------------- + INTEGER , INTENT(in ) :: kt ! ocean time-step index + INTEGER , INTENT(in ) :: Kmm, Krhs ! ocean time level indices + INTEGER , INTENT(in ) :: kit000 ! first time step index + CHARACTER(len=3) , INTENT(in ) :: cdtype ! =TRA or TRC (tracer indicator) + INTEGER , INTENT(in ) :: kjpt ! number of tracers + INTEGER , INTENT(in ) :: kn_cen_h ! =2/4 (2nd or 4th order scheme) + INTEGER , INTENT(in ) :: kn_cen_v ! =2/4 (2nd or 4th order scheme) + ! TEMP: [tiling] This can be A2D(nn_hls) after all lbc_lnks removed in the nn_hls = 2 case in tra_adv_fct + REAL(wp), DIMENSION(jpi,jpj,jpk ), INTENT(in ) :: pU, pV, pW ! 3 ocean volume flux components + REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt,jpt), INTENT(inout) :: pt ! tracers and RHS of tracer equation + ! + INTEGER :: ji, jj, jk, jn ! dummy loop indices + INTEGER :: ierr ! local integer + REAL(wp) :: zC2t_u, zC4t_u ! local scalars + REAL(wp) :: zC2t_v, zC4t_v ! - - + REAL(wp) :: zftw_kp1 + REAL(wp), DIMENSION(A2D(1)) :: zft_u, zft_v + REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: zdt_u, zdt_v + REAL(wp), DIMENSION(:,:,:) , ALLOCATABLE :: ztw + !!---------------------------------------------------------------------- + ! +#if defined key_loop_fusion + CALL tra_adv_cen_lf ( kt, nit000, cdtype, pU, pV, pW, Kmm, pt, kjpt, Krhs, kn_cen_h, kn_cen_v ) +#else + IF( .NOT. l_istiled .OR. ntile == 1 ) THEN ! Do only on the first tile + IF( kt == kit000 ) THEN + IF(lwp) WRITE(numout,*) + IF(lwp) WRITE(numout,*) 'tra_adv_cen : centered advection scheme on ', cdtype, ' order h/v =', kn_cen_h,'/', kn_cen_v + IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~ ' + ENDIF + ! ! set local switches + l_trd = .FALSE. + l_hst = .FALSE. + l_ptr = .FALSE. + IF( ( cdtype == 'TRA' .AND. l_trdtra ) .OR. ( cdtype == 'TRC' .AND. l_trdtrc ) ) l_trd = .TRUE. + IF( cdtype == 'TRA' .AND. ( iom_use( 'sophtadv' ) .OR. iom_use( 'sophtadv' ) ) ) l_ptr = .TRUE. + IF( cdtype == 'TRA' .AND. ( iom_use("uadv_heattr") .OR. iom_use("vadv_heattr") .OR. & + & iom_use("uadv_salttr") .OR. iom_use("vadv_salttr") ) ) l_hst = .TRUE. + ENDIF + ! + IF( kn_cen_h == 4 ) ALLOCATE( zdt_u(A2D(2)) , zdt_v(A2D(2)) ) ! horizontal 4th order only + IF( kn_cen_v == 4 ) ALLOCATE( ztw(A2D(nn_hls),jpk) ) ! vertical 4th order only + ! + DO jn = 1, kjpt !== loop over the tracers ==! + ! + SELECT CASE( kn_cen_h ) !-- Horizontal divergence of advective fluxes --! + ! +!!st limitation : does not take into acccount iceshelf specificity +!! in case of linssh + CASE( 2 ) !* 2nd order centered + DO jk = 1, jpkm1 + ! + DO_2D( 1, 0, 1, 0 ) ! Horizontal fluxes at layer jk + zft_u(ji,jj) = 0.5_wp * pU(ji,jj,jk) * ( pt(ji,jj,jk,jn,Kmm) + pt(ji+1,jj ,jk,jn,Kmm) ) + zft_v(ji,jj) = 0.5_wp * pV(ji,jj,jk) * ( pt(ji,jj,jk,jn,Kmm) + pt(ji ,jj+1,jk,jn,Kmm) ) + END_2D + ! + DO_2D( 0, 0, 0, 0 ) ! Horizontal divergence of advective fluxes + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - ( zft_u(ji,jj) - zft_u(ji-1,jj ) & + & + zft_v(ji,jj) - zft_v(ji ,jj-1) ) * r1_e1e2t(ji,jj) & + & / e3t(ji,jj,jk,Kmm) + END_2D + END DO + ! + CASE( 4 ) !* 4th order centered + DO jk = 1, jpkm1 + DO_2D( 2, 1, 2, 1 ) ! masked gradient + zdt_u(ji,jj) = ( pt(ji+1,jj ,jk,jn,Kmm) - pt(ji,jj,jk,jn,Kmm) ) * umask(ji,jj,jk) + zdt_v(ji,jj) = ( pt(ji ,jj+1,jk,jn,Kmm) - pt(ji,jj,jk,jn,Kmm) ) * vmask(ji,jj,jk) + END_2D + ! + DO_2D( 1, 0, 1, 0 ) ! Horizontal advective fluxes + zC2t_u = pt(ji,jj,jk,jn,Kmm) + pt(ji+1,jj ,jk,jn,Kmm) ! C2 interpolation of T at u- & v-points (x2) + zC2t_v = pt(ji,jj,jk,jn,Kmm) + pt(ji ,jj+1,jk,jn,Kmm) + ! ! C4 interpolation of T at u- & v-points (x2) + zC4t_u = zC2t_u + r1_6 * ( zdt_u(ji-1,jj ) - zdt_u(ji+1,jj ) ) + zC4t_v = zC2t_v + r1_6 * ( zdt_v(ji ,jj-1) - zdt_v(ji ,jj+1) ) + ! ! C4 fluxes + zft_u(ji,jj) = 0.5_wp * pU(ji,jj,jk) * zC4t_u + zft_v(ji,jj) = 0.5_wp * pV(ji,jj,jk) * zC4t_v + END_2D + ! + DO_2D( 0, 0, 0, 0 ) ! Horizontal divergence of advective fluxes + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - ( zft_u(ji,jj) - zft_u(ji-1,jj ) & + & + zft_v(ji,jj) - zft_v(ji ,jj-1) ) * r1_e1e2t(ji,jj) & + & / e3t(ji,jj,jk,Kmm) + END_2D + END DO + ! + CASE DEFAULT + CALL ctl_stop( 'traadv_cen: wrong value for nn_cen' ) + END SELECT + ! +#define zft_w zft_u + ! + IF( ln_linssh ) THEN !* top value (linear free surf. only as zwz is multiplied by wmask) + DO_2D( 0, 0, 0, 0 ) + zft_w(ji,jj) = pW(ji,jj,1) * pt(ji,jj,1,jn,Kmm) + END_2D + ELSE + DO_2D( 0, 0, 0, 0 ) + zft_w(ji,jj) = 0._wp + END_2D + ENDIF + ! + SELECT CASE( kn_cen_v ) !-- Vertical divergence of advective fluxes --! (interior) + ! + CASE( 2 ) !* 2nd order centered + DO jk = 1, jpk-2 + DO_2D( 0, 0, 0, 0 ) ! Vertical fluxes + zftw_kp1 = 0.5 * pW(ji,jj,jk+1) * ( pt(ji,jj,jk+1,jn,Kmm) + pt(ji,jj,jk,jn,Kmm) ) * wmask(ji,jj,jk+1) + ! + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - ( zft_w(ji,jj) - zftw_kp1 ) * r1_e1e2t(ji,jj) & + & / e3t(ji,jj,jk,Kmm) + zft_w(ji,jj) = zftw_kp1 + END_2D + END DO + jk = jpkm1 ! bottom vertical flux set to zero for all tracers + DO_2D( 0, 0, 0, 0 ) + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - zft_w(ji,jj) * r1_e1e2t(ji,jj) & + & / e3t(ji,jj,jk,Kmm) + END_2D + ! + CASE( 4 ) !* 4th order compact + CALL interp_4th_cpt( pt(:,:,:,jn,Kmm) , ztw ) ! ztw = interpolated value of T at w-point + ! + DO jk = 1, jpk-2 + ! + DO_2D( 0, 0, 0, 0 ) + zftw_kp1 = pW(ji,jj,jk+1) * ztw(ji,jj,jk+1) * wmask(ji,jj,jk+1) + ! ! Divergence of advective fluxes + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - ( zft_w(ji,jj) - zftw_kp1 ) * r1_e1e2t(ji,jj) & + & / e3t(ji,jj,jk,Kmm) + ! ! update + zft_w(ji,jj) = zftw_kp1 + END_2D + ! + END DO + ! + jk = jpkm1 ! bottom vertical flux set to zero for all tracers + DO_2D( 0, 0, 0, 0 ) + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - zft_w(ji,jj) * r1_e1e2t(ji,jj) & + & / e3t(ji,jj,jk,Kmm) + END_2D + ! + END SELECT + ! +#undef zft_w + ! ! trend diagnostics +!!gm + !!st to be done with the whole rewritting of trd +!! trd routine arguments MUST be changed adding jk and zwx, zwy in 2D +!! IF( l_trd ) THEN +!! CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jptra_xad, zwx, pU, pt(:,:,:,jn,Kmm) ) +!! CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jptra_yad, zwy, pV, pt(:,:,:,jn,Kmm) ) +!! CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jptra_zad, zwz, pW, pt(:,:,:,jn,Kmm) ) +!! ENDIF +!! ! ! "Poleward" heat and salt transports +!! IF( l_ptr ) CALL dia_ptr_hst( jn, 'adv', zwy(:,:,:) ) +!! ! ! heat and salt transport +!! IF( l_hst ) CALL dia_ar5_hst( jn, 'adv', zwx(:,:,:), zwy(:,:,:) ) + ! + END DO + ! + IF( kn_cen_h == 4 ) DEALLOCATE( zdt_u , zdt_v ) ! horizontal 4th order only + IF( kn_cen_v == 4 ) DEALLOCATE( ztw ) ! vertical 4th order only + ! +#endif + END SUBROUTINE tra_adv_cen + + + SUBROUTINE tra_adv_cen_hls1( kt, kit000, cdtype, pU, pV, pW, & & Kmm, pt, kjpt, Krhs, kn_cen_h, kn_cen_v ) !!---------------------------------------------------------------------- !! *** ROUTINE tra_adv_cen *** @@ -141,6 +457,12 @@ CONTAINS CASE DEFAULT CALL ctl_stop( 'traadv_cen: wrong value for nn_cen' ) END SELECT + DO_3D( 0, 0, 0, 0, 1, jpkm1 ) !-- Divergence of advective fluxes --! + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) & + & - ( zwx(ji,jj,jk) - zwx(ji-1,jj ,jk ) & + & + zwy(ji,jj,jk) - zwy(ji ,jj-1,jk ) ) & + & * r1_e1e2t(ji,jj) / e3t(ji,jj,jk,Kmm) + END_3D ! SELECT CASE( kn_cen_v ) !-- Vertical fluxes --! (interior) ! @@ -171,11 +493,17 @@ CONTAINS ! DO_3D( 0, 0, 0, 0, 1, jpkm1 ) !-- Divergence of advective fluxes --! pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) & - & - ( zwx(ji,jj,jk) - zwx(ji-1,jj ,jk ) & - & + zwy(ji,jj,jk) - zwy(ji ,jj-1,jk ) & - & + zwz(ji,jj,jk) - zwz(ji ,jj ,jk+1) ) & + & - ( zwz(ji,jj,jk) - zwz(ji ,jj ,jk+1) ) & & * r1_e1e2t(ji,jj) / e3t(ji,jj,jk,Kmm) END_3D +! +!!st DO_3D( 0, 0, 0, 0, 1, jpkm1 ) !-- Divergence of advective fluxes --! +!!st pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) & +!!st & - ( zwx(ji,jj,jk) - zwx(ji-1,jj ,jk ) & +!!st & + zwy(ji,jj,jk) - zwy(ji ,jj-1,jk ) & +!!st & + zwz(ji,jj,jk) - zwz(ji ,jj ,jk+1) ) & +!!st & * r1_e1e2t(ji,jj) / e3t(ji,jj,jk,Kmm) +!!st END_3D ! ! trend diagnostics IF( l_trd ) THEN CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jptra_xad, zwx, pU, pt(:,:,:,jn,Kmm) ) @@ -190,7 +518,7 @@ CONTAINS END DO ! #endif - END SUBROUTINE tra_adv_cen + END SUBROUTINE tra_adv_cen_hls1 !!====================================================================== END MODULE traadv_cen diff --git a/src/OCE/TRA/traadv_mus.F90 b/src/OCE/TRA/traadv_mus.F90 index 4c4b0437c..c22fcfd01 100644 --- a/src/OCE/TRA/traadv_mus.F90 +++ b/src/OCE/TRA/traadv_mus.F90 @@ -9,6 +9,7 @@ MODULE traadv_mus !! 3.2 ! 2010-05 (C. Ethe, G. Madec) merge TRC-TRA + switch from velocity to transport !! 3.4 ! 2012-06 (P. Oddo, M. Vichi) include the upstream where needed !! 3.7 ! 2015-09 (G. Madec) add the ice-shelf cavities boundary condition + !! 4.5 ! 2022-06 (S. Techene, G, Madec) refactorization to reduce local memory usage !!---------------------------------------------------------------------- !!---------------------------------------------------------------------- @@ -34,7 +35,9 @@ MODULE traadv_mus IMPLICIT NONE PRIVATE - PUBLIC tra_adv_mus ! routine called by traadv.F90 + PUBLIC tra_adv_mus ! routine called by traadv.F90 + PUBLIC tra_adv_mus_hls1 ! routine called by traadv.F90 + REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: upsmsk !: mixed upstream/centered scheme near some straits ! ! and in closed seas (orca 2 and 1 configurations) @@ -55,6 +58,217 @@ MODULE traadv_mus CONTAINS SUBROUTINE tra_adv_mus( kt, kit000, cdtype, p2dt, pU, pV, pW, & + & Kbb, Kmm, pt, kjpt, Krhs, ld_msc_ups ) + !!---------------------------------------------------------------------- + !! *** ROUTINE tra_adv_mus *** + !! + !! ** Purpose : Compute the now trend due to total advection of tracers + !! using a MUSCL scheme (Monotone Upstream-centered Scheme for + !! Conservation Laws) and add it to the general tracer trend. + !! + !! ** Method : MUSCL scheme plus centered scheme at ocean boundaries + !! ld_msc_ups=T : + !! + !! ** Action : - update pt(:,:,:,:,Krhs) with the now advective tracer trends + !! - send trends to trdtra module for further diagnostcs (l_trdtra=T) + !! - poleward advective heat and salt transport (ln_diaptr=T) + !! + !! References : Estubier, A., and M. Levy, Notes Techn. Pole de Modelisation + !! IPSL, Sept. 2000 (http://www.lodyc.jussieu.fr/opa) + !!---------------------------------------------------------------------- + INTEGER , INTENT(in ) :: kt ! ocean time-step index + INTEGER , INTENT(in ) :: Kbb, Kmm, Krhs ! ocean time level indices + INTEGER , INTENT(in ) :: kit000 ! first time step index + CHARACTER(len=3) , INTENT(in ) :: cdtype ! =TRA or TRC (tracer indicator) + INTEGER , INTENT(in ) :: kjpt ! number of tracers + LOGICAL , INTENT(in ) :: ld_msc_ups ! use upstream scheme within muscl + REAL(wp) , INTENT(in ) :: p2dt ! tracer time-step + ! TEMP: [tiling] This can be A2D(nn_hls) after all lbc_lnks removed in the nn_hls = 2 case in tra_adv_fct + REAL(wp), DIMENSION(jpi,jpj,jpk ), INTENT(in ) :: pU, pV, pW ! 3 ocean volume flux components + REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt,jpt), INTENT(inout) :: pt ! tracers and RHS of tracer equation + ! + INTEGER :: ji, jj, jk, jn ! dummy loop indices + INTEGER :: ierr ! local integer + INTEGER :: ik + REAL(wp) :: zu, z0u, zzslpx, zzwx, zw , zalpha ! local scalars + REAL(wp) :: zv, z0v, zzslpy, zzwy, z0w ! - - + REAL(wp) :: zdzt_kp2, zslpz_kp1, zfW_kp1 + REAL(wp), DIMENSION(A2D(2)) :: zdxt, zslpx, zwx ! 2D workspace + REAL(wp), DIMENSION(A2D(2)) :: zdyt, zslpy, zwy ! - - + !!---------------------------------------------------------------------- + ! + IF( .NOT. l_istiled .OR. ntile == 1 ) THEN ! Do only on the first tile + IF( kt == kit000 ) THEN + IF(lwp) WRITE(numout,*) + IF(lwp) WRITE(numout,*) 'tra_adv : MUSCL advection scheme on ', cdtype + IF(lwp) WRITE(numout,*) ' : mixed up-stream ', ld_msc_ups + IF(lwp) WRITE(numout,*) '~~~~~~~' + IF(lwp) WRITE(numout,*) + ! + ! Upstream / MUSCL scheme indicator + ! + ALLOCATE( xind(jpi,jpj,jpk), STAT=ierr ) + xind(:,:,:) = 1._wp ! set equal to 1 where up-stream is not needed + IF( ld_msc_ups ) THEN ! define the upstream indicator (if asked) + DO jk = 1, jpkm1 + xind(:,:,jk) = 1._wp & ! =>1 where up-stream is not needed + & - rnfmsk(:,:) * rnfmsk_z(jk) * tmask(:,:,jk) ! =>0 near runoff mouths (& closed sea outflows) + END DO + ENDIF + ! + ENDIF + ! + l_trd = .FALSE. + l_hst = .FALSE. + l_ptr = .FALSE. + IF( ( cdtype == 'TRA' .AND. l_trdtra ) .OR. ( cdtype == 'TRC' .AND. l_trdtrc ) ) l_trd = .TRUE. + IF( l_diaptr .AND. cdtype == 'TRA' .AND. ( iom_use( 'sophtadv' ) .OR. iom_use( 'sophtadv' ) ) ) l_ptr = .TRUE. + IF( l_iom .AND. cdtype == 'TRA' .AND. ( iom_use("uadv_heattr") .OR. iom_use("vadv_heattr") .OR. & + & iom_use("uadv_salttr") .OR. iom_use("vadv_salttr") ) ) l_hst = .TRUE. + ENDIF + ! + ! + DO jn = 1, kjpt !== loop over the tracers ==! + ! + DO jk = 1, jpkm1 + ! !* Horizontal advective fluxes + ! + ! !-- first guess of the slopes + DO_2D( 2, 1, 2, 1 ) + zdxt(ji,jj) = ( pt(ji+1,jj ,jk,jn,Kbb) - pt(ji,jj,jk,jn,Kbb) ) * umask(ji,jj,jk) + zdyt(ji,jj) = ( pt(ji ,jj+1,jk,jn,Kbb) - pt(ji,jj,jk,jn,Kbb) ) * vmask(ji,jj,jk) + END_2D + ! !-- Slopes of tracer + DO_2D( 1, 1, 1, 1 ) + ! ! 1/2 Slopes at T-point (set to 0 if adjectent slopes are of opposite sign) + zzslpx = ( zdxt(ji,jj) + zdxt(ji-1,jj ) ) & + & * ( 0.25_wp + SIGN( 0.25_wp, zdxt(ji,jj) * zdxt(ji-1,jj ) ) ) + zzslpy = ( zdyt(ji,jj) + zdyt(ji ,jj-1) ) & + & * ( 0.25_wp + SIGN( 0.25_wp, zdyt(ji,jj) * zdyt(ji ,jj-1) ) ) + ! ! Slopes limitation + zslpx(ji,jj) = SIGN( 1.0_wp, zzslpx ) * MIN( ABS( zzslpx ), & + & 2._wp*ABS( zdxt (ji-1,jj) ), & + & 2._wp*ABS( zdxt (ji ,jj) ) ) + zslpy(ji,jj) = SIGN( 1.0_wp, zzslpy ) * MIN( ABS( zzslpy ), & + & 2._wp*ABS( zdyt (ji,jj-1) ), & + & 2._wp*ABS( zdyt (ji,jj ) ) ) + END_2D +!!gm + !!st ticket ? comparaison pommes et carrottes ABS(zzslpx) et 2._wp*ABS( zdxt (ji-1,jj) ) + ! + DO_2D( 1, 0, 1, 0 ) !-- MUSCL horizontal advective fluxes + z0u = SIGN( 0.5_wp, pU(ji,jj,jk) ) + zalpha = 0.5_wp - z0u + zu = z0u - 0.5_wp * pU(ji,jj,jk) * p2dt * r1_e1e2u(ji,jj) / e3u(ji,jj,jk,Kmm) + zzwx = pt(ji+1,jj,jk,jn,Kbb) + xind(ji,jj,jk) * zu * zslpx(ji+1,jj) + zzwy = pt(ji ,jj,jk,jn,Kbb) + xind(ji,jj,jk) * zu * zslpx(ji ,jj) + zwx(ji,jj) = pU(ji,jj,jk) * ( zalpha * zzwx + (1._wp-zalpha) * zzwy ) + ! + z0v = SIGN( 0.5_wp, pV(ji,jj,jk) ) + zalpha = 0.5_wp - z0v + zv = z0v - 0.5_wp * pV(ji,jj,jk) * p2dt * r1_e1e2v(ji,jj) / e3v(ji,jj,jk,Kmm) + zzwx = pt(ji,jj+1,jk,jn,Kbb) + xind(ji,jj,jk) * zv * zslpy(ji,jj+1) + zzwy = pt(ji,jj ,jk,jn,Kbb) + xind(ji,jj,jk) * zv * zslpy(ji,jj ) + zwy(ji,jj) = pV(ji,jj,jk) * ( zalpha * zzwx + (1._wp-zalpha) * zzwy ) + END_2D + ! + DO_2D( 0, 0, 0, 0 ) !-- Tracer advective trend + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - ( zwx(ji,jj) - zwx(ji-1,jj ) & + & + zwy(ji,jj) - zwy(ji ,jj-1) ) & + & * r1_e1e2t(ji,jj) / e3t(ji,jj,jk,Kmm) + END_2D + END DO +!!gm + !!st to be done with the whole rewritting of trd +!! trd routine arguments MUST be changed adding jk and zwx, zwy in 2D +!! +!! ! ! trend diagnostics +!! IF( l_trd ) THEN +!! CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jk, jptra_xad, zwx(:,:), pU, pt(:,:,:,jn,Kbb) ) +!! CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jk, jptra_yad, zwy(:,:), pV, pt(:,:,:,jn,Kbb) ) +!! END IF +!! ! ! "Poleward" heat and salt transports +!! IF( l_ptr ) CALL dia_ptr_hst( jn, jk, 'adv', zwy(:,:) ) +!! ! ! heat transport +!! IF( l_hst ) CALL dia_ar5_hst( jn, jk, 'adv', zwx(:,:), zwy(:,:) ) + ! + ! !* Vertical advective fluxes + ! +#define zdzt_kp1 zdxt +#define zslpz zslpx +#define zfW zwx + + zfW (A2D(0)) = 0._wp ! anciennement zwx at jk = 1 + ! ! anciennement zwx at jk = 2 + DO_2D( 0, 0, 0, 0 ) + zdzt_kp1(ji,jj) = tmask(ji,jj,2) * ( pt(ji,jj,1,jn,Kbb) - pt(ji,jj,2,jn,Kbb) ) + END_2D + zslpz (A2D(0)) = 0._wp ! anciennement zslpx at jk = 1 + ! + IF( ln_linssh ) THEN !-- linear ssh : non zero top values + DO_2D( 0, 0, 0, 0 ) ! at the ocean surface + zfW(ji,jj) = pW(ji,jj,1) * pt(ji,jj,1,jn,Kbb) ! surface flux + END_2D + IF( ln_isfcav ) THEN ! ice-shelf cavities (top of the ocean) + DO_2D( 0, 0, 0, 0 ) ! update pt(Krhs) under the ice-shelf + ik = mikt(ji,jj) ! the flux at ik-1 is zero ( inside ice-shelf ) + IF( ik > 1 ) THEN + pt(ji,jj,ik,jn,Krhs) = pt(ji,jj,ik,jn,Krhs) - pW(ji,jj,ik) * pt(ji,jj,ik,jn,Kbb) & + & * r1_e1e2t(ji,jj) / e3t(ji,jj,ik,Kmm) + ENDIF + END_2D + ENDIF + ENDIF + ! + ! wmask usage for computing zw and zwk is needed in isf case and linear ssh + ! + ! + DO jk = 1, jpkm1 + IF( jk < jpkm1 ) THEN + DO_2D( 0, 0, 0, 0 ) + ! !-- Slopes of tracer + ! ! masked vertical gradient at jk+2 + zdzt_kp2 = ( pt(ji,jj,jk+1,jn,Kbb) - pt(ji,jj,jk+2,jn,Kbb) ) * tmask(ji,jj,jk+2) !!st wmask(ji,jj,jk+2) + ! ! vertical slope at jk+1 + zslpz_kp1 = ( zdzt_kp1(ji,jj) + zdzt_kp2 ) & + & * ( 0.25_wp + SIGN( 0.25_wp, zdzt_kp1(ji,jj) * zdzt_kp2 ) ) + ! ! slope limitation + zslpz_kp1 = SIGN( 1.0_wp, zslpz_kp1 ) * MIN( ABS( zslpz_kp1 ), & + & 2.*ABS( zdzt_kp2 ), & + & 2.*ABS( zdzt_kp1(ji,jj) ) ) + ! !-- vertical advective flux at jk+1 + ! ! caution: zfW_kp1 is masked for ice-shelf cavities + ! ! since top fluxes already added to pt(Krhs) before the vertical loop + z0w = SIGN( 0.5_wp, pW(ji,jj,jk+1) ) + zalpha = 0.5_wp + z0w + zw = z0w - 0.5_wp * pW(ji,jj,jk+1) * p2dt * r1_e1e2t(ji,jj) / e3w(ji,jj,jk+1,Kmm) + zzwx = pt(ji,jj,jk+1,jn,Kbb) + xind(ji,jj,jk) * zw * zslpz_kp1 + zzwy = pt(ji,jj,jk ,jn,Kbb) + xind(ji,jj,jk) * zw * zslpz(ji,jj) + zfW_kp1 = pW(ji,jj,jk+1) * ( zalpha * zzwx + (1.-zalpha) * zzwy ) * wmask(ji,jj,jk)!!st * wmask(ji,jj,jk+1) + ! !-- vertical advective trend at jk + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - ( zfW(ji,jj) - zfW_kp1 ) & + & * r1_e1e2t(ji,jj) / e3t(ji,jj,jk,Kmm) + ! ! updates for next level + zdzt_kp1(ji,jj) = zdzt_kp2 + zslpz (ji,jj) = zslpz_kp1 + zfW (ji,jj) = zfW_kp1 + END_2D + ELSE + DO_2D( 0, 0, 0, 0 ) !-- vertical advective trend at jpkm1 + pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - zfW(ji,jj) & + & * r1_e1e2t(ji,jj) / e3t(ji,jj,jk,Kmm) + END_2D + ENDIF + END DO ! end of jk loop + ! +!!gm + !!st idem see above +!! ! ! send trends for diagnostic +!! IF( l_trd ) CALL trd_tra( kt, Kmm, Krhs, cdtype, jn, jptra_zad, zwx, pW, pt(:,:,:,jn,Kbb) ) + ! + END DO ! end of tracer loop + ! + END SUBROUTINE tra_adv_mus + + + SUBROUTINE tra_adv_mus_hls1( kt, kit000, cdtype, p2dt, pU, pV, pW, & & Kbb, Kmm, pt, kjpt, Krhs, ld_msc_ups ) !!---------------------------------------------------------------------- !! *** ROUTINE tra_adv_mus *** @@ -178,7 +392,7 @@ CONTAINS ! DO_3D( 0, 0, 0, 0, 1, jpkm1 ) !-- Tracer advective trend pt(ji,jj,jk,jn,Krhs) = pt(ji,jj,jk,jn,Krhs) - ( zwx(ji,jj,jk) - zwx(ji-1,jj ,jk ) & - & + zwy(ji,jj,jk) - zwy(ji ,jj-1,jk ) ) & + & + zwy(ji,jj,jk) - zwy(ji ,jj-1,jk ) ) & & * r1_e1e2t(ji,jj) / e3t(ji,jj,jk,Kmm) END_3D ! ! trend diagnostics @@ -239,7 +453,7 @@ CONTAINS ! END DO ! end of tracer loop ! - END SUBROUTINE tra_adv_mus + END SUBROUTINE tra_adv_mus_hls1 !!====================================================================== END MODULE traadv_mus diff --git a/src/TOP/TRP/trcadv.F90 b/src/TOP/TRP/trcadv.F90 index 86776d878..bfd2cf390 100644 --- a/src/TOP/TRP/trcadv.F90 +++ b/src/TOP/TRP/trcadv.F90 @@ -8,6 +8,7 @@ MODULE trcadv !! 3.7 ! 2014-05 (G. Madec, C. Ethe) Add 2nd/4th order cases for CEN and FCT schemes !! 4.0 ! 2017-09 (G. Madec) remove vertical time-splitting option !! 4.5 ! 2021-08 (G. Madec, S. Techene) add advective velocities as optional arguments + !! - ! 2022-06 (S. Techene, G, Madec) refactorization to reduce local memory usage !!---------------------------------------------------------------------- #if defined key_top !!---------------------------------------------------------------------- @@ -156,11 +157,19 @@ CONTAINS SELECT CASE ( nadv ) !== compute advection trend and add it to general trend ==! ! CASE ( np_CEN ) ! Centered : 2nd / 4th order - CALL tra_adv_cen ( kt, nittrc000,'TRC', zuu, zvv, zww, Kmm, ptr, jptra, Krhs, nn_cen_h, nn_cen_v ) + IF( nn_hls == 1 ) THEN + CALL tra_adv_cen_hls1( kt, nittrc000,'TRC', zuu, zvv, zww, Kmm, ptr, jptra, Krhs, nn_cen_h, nn_cen_v ) + ELSE + CALL tra_adv_cen ( kt, nittrc000,'TRC', zuu, zvv, zww, Kmm, ptr, jptra, Krhs, nn_cen_h, nn_cen_v ) + ENDIF CASE ( np_FCT ) ! FCT : 2nd / 4th order CALL tra_adv_fct( kt, nittrc000,'TRC', rDt_trc, zuu, zvv, zww, Kbb, Kmm, ptr, jptra, Krhs, nn_fct_h, nn_fct_v ) CASE ( np_MUS ) ! MUSCL + IF( nn_hls == 1 ) THEN + CALL tra_adv_mus_hls1( kt, nittrc000,'TRC', rDt_trc, zuu, zvv, zww, Kbb, Kmm, ptr, jptra, Krhs, ln_mus_ups ) + ELSE CALL tra_adv_mus( kt, nittrc000,'TRC', rDt_trc, zuu, zvv, zww, Kbb, Kmm, ptr, jptra, Krhs, ln_mus_ups ) + ENDIF CASE ( np_UBS ) ! UBS CALL tra_adv_ubs ( kt, nittrc000,'TRC', rDt_trc, zuu, zvv, zww, Kbb, Kmm, ptr, jptra, Krhs, nn_ubs_v ) CASE ( np_QCK ) ! QUICKEST -- GitLab