MODULE trddyn !!====================================================================== !! *** MODULE trddyn *** !! Ocean diagnostics: ocean dynamic trends !!===================================================================== !! History : 3.5 ! 2012-02 (G. Madec) creation from trdmod: split DYN and TRA trends !! and manage 3D trends output for U, V, and KE !!---------------------------------------------------------------------- !!---------------------------------------------------------------------- !! trd_dyn : manage the type of momentum trend diagnostics (3D I/O, domain averaged, KE) !! trd_dyn_iom : output 3D momentum and/or tracer trends using IOM !! trd_dyn_init : initialization step !!---------------------------------------------------------------------- USE oce ! ocean dynamics and tracers variables USE dom_oce ! ocean space and time domain variables USE phycst ! physical constants USE sbc_oce ! surface boundary condition: ocean USE zdf_oce ! ocean vertical physics: variables USE trd_oce ! trends: ocean variables USE trdken ! trends: Kinetic ENergy USE trdglo ! trends: global domain averaged USE trdvor ! trends: vertical averaged vorticity USE trdmxl ! trends: mixed layer averaged ! USE in_out_manager ! I/O manager USE lbclnk ! lateral boundary condition USE iom ! I/O manager library USE lib_mpp ! MPP library IMPLICIT NONE PRIVATE PUBLIC trd_dyn ! called by all dynXXX modules INTERFACE trd_dyn module procedure trd_dyn_3d, trd_dyn_2d END INTERFACE REAL(wp), ALLOCATABLE, DIMENSION(:,:,:), SAVE :: zutrd_hpg, zvtrd_hpg REAL(wp), ALLOCATABLE, DIMENSION(:,:,:), SAVE :: zutrd_pvo, zvtrd_pvo REAL(wp), ALLOCATABLE, DIMENSION(:,:,:), SAVE :: zutrd_bfr, zvtrd_bfr !! * Substitutions # include "vectopt_loop_substitute.h90" !!---------------------------------------------------------------------- !! NEMO/OCE 4.0 , NEMO Consortium (2018) !! $Id$ !! Software governed by the CeCILL license (see ./LICENSE) !!---------------------------------------------------------------------- CONTAINS SUBROUTINE trd_dyn_3d( putrd, pvtrd, ktrd, kt ) !!--------------------------------------------------------------------- !! *** ROUTINE trd_dyn_3d *** !! !! ** Purpose : Dispatch momentum trend computation, e.g. 3D output, !! integral constraints, barotropic vorticity, kinetic enrgy, !! and/or mixed layer budget. !!---------------------------------------------------------------------- REAL(wp), DIMENSION(:,:,:), INTENT(inout) :: putrd, pvtrd ! U and V trends INTEGER , INTENT(in ) :: ktrd ! trend index INTEGER , INTENT(in ) :: kt ! time step REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: zue, zve ! temporary 2D arrays INTEGER :: jk !!---------------------------------------------------------------------- ! putrd(:,:,:) = putrd(:,:,:) * umask(:,:,:) ! mask the trends pvtrd(:,:,:) = pvtrd(:,:,:) * vmask(:,:,:) ! !!gm NB : here a lbc_lnk should probably be added SELECT CASE( ktrd ) CASE( jpdyn_hpg_save ) ! ! save 3D HPG trends to possibly have barotropic part corrected later before writing out ALLOCATE( zutrd_hpg(jpi,jpj,jpk), zvtrd_hpg(jpi,jpj,jpk) ) zutrd_hpg(:,:,:) = putrd(:,:,:) zvtrd_hpg(:,:,:) = pvtrd(:,:,:) CASE( jpdyn_pvo_save ) ! ! save 3D coriolis trends to possibly have barotropic part corrected later before writing out ALLOCATE( zutrd_pvo(jpi,jpj,jpk), zvtrd_pvo(jpi,jpj,jpk) ) zutrd_pvo(:,:,:) = putrd(:,:,:) zvtrd_pvo(:,:,:) = pvtrd(:,:,:) CASE DEFAULT IF( ktrd == jpdyn_spg ) THEN ! For explicit scheme SPG trends come here as 3D fields ! Add SPG trend to 3D HPG trend and also output as 2D diagnostic in own right. CALL trd_dyn_iom_2d( putrd(:,:,1), pvtrd(:,:,1), jpdyn_spg, kt ) putrd(:,:,:) = putrd(:,:,:) + zutrd_hpg(:,:,:) pvtrd(:,:,:) = pvtrd(:,:,:) + zvtrd_hpg(:,:,:) DEALLOCATE( zutrd_hpg, zvtrd_hpg ) ENDIF IF( ktrd == jpdyn_bfr ) THEN ! ! Add 3D part of BFR trend minus its depth-mean part to depth-mean trend already saved. ALLOCATE( zue(jpi,jpj), zve(jpi,jpj) ) zue(:,:) = e3u_a(:,:,1) * putrd(:,:,1) * umask(:,:,1) zve(:,:) = e3v_a(:,:,1) * pvtrd(:,:,1) * vmask(:,:,1) DO jk = 2, jpkm1 zue(:,:) = zue(:,:) + e3u_a(:,:,jk) * putrd(:,:,jk) * umask(:,:,jk) zve(:,:) = zve(:,:) + e3v_a(:,:,jk) * pvtrd(:,:,jk) * vmask(:,:,jk) END DO DO jk = 1, jpkm1 putrd(:,:,jk) = zutrd_bfr(:,:,jk) + putrd(:,:,jk) - zue(:,:) * r1_hu_a(:,:) pvtrd(:,:,jk) = zvtrd_bfr(:,:,jk) + pvtrd(:,:,jk) - zve(:,:) * r1_hv_a(:,:) END DO DEALLOCATE( zue, zve, zutrd_bfr, zvtrd_bfr ) ENDIF !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ! 3D output of momentum and/or tracers trends using IOM interface !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< IF( ln_dyn_trd ) CALL trd_dyn_iom_3d( putrd, pvtrd, ktrd, kt ) !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ! Integral Constraints Properties for momentum and/or tracers trends !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< IF( ln_glo_trd ) CALL trd_glo( putrd, pvtrd, ktrd, 'DYN', kt ) !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ! Kinetic Energy trends !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IF( ln_KE_trd ) CALL trd_ken( putrd, pvtrd, ktrd, kt ) !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ! Vorticity trends !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IF( ln_vor_trd ) CALL trd_vor( putrd, pvtrd, ktrd, kt ) !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ! Mixed layer trends for active tracers !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< !!gm IF( ln_dyn_mxl ) CALL trd_mxl_dyn ! END SELECT ! END SUBROUTINE trd_dyn_3d SUBROUTINE trd_dyn_2d( putrd, pvtrd, ktrd, kt ) !!--------------------------------------------------------------------- !! *** ROUTINE trd_mod *** !! !! ** Purpose : Dispatch momentum trend computation, e.g. 2D output, !! integral constraints, barotropic vorticity, kinetic enrgy, !! and/or mixed layer budget. !!---------------------------------------------------------------------- REAL(wp), DIMENSION(:,:), INTENT(inout) :: putrd, pvtrd ! U and V trends INTEGER , INTENT(in ) :: ktrd ! trend index INTEGER , INTENT(in ) :: kt ! time step INTEGER :: jk !!---------------------------------------------------------------------- ! putrd(:,:) = putrd(:,:) * umask(:,:,1) ! mask the trends pvtrd(:,:) = pvtrd(:,:) * vmask(:,:,1) ! !!gm NB : here a lbc_lnk should probably be added SELECT CASE(ktrd) CASE ( jpdyn_hpg_corr ) ! ! Remove "first-guess" SPG trend from 3D HPG trend. DO jk = 1, jpkm1 zutrd_hpg(:,:,jk) = zutrd_hpg(:,:,jk) - putrd(:,:) zvtrd_hpg(:,:,jk) = zvtrd_hpg(:,:,jk) - pvtrd(:,:) ENDDO CALL trd_dyn_iom_2d( putrd, pvtrd, jpdyn_hpg_corr, kt ) CASE( jpdyn_pvo_corr ) ! ! Remove "first-guess" barotropic coriolis trend from 3D PVO trend. DO jk = 1, jpkm1 zutrd_pvo(:,:,jk) = zutrd_pvo(:,:,jk) - putrd(:,:) zvtrd_pvo(:,:,jk) = zvtrd_pvo(:,:,jk) - pvtrd(:,:) ENDDO CALL trd_dyn_iom_2d( putrd, pvtrd, jpdyn_pvo_corr, kt ) CASE( jpdyn_spg ) ! ! For split-explicit scheme SPG trends come here as 2D fields ! Add SPG trend to 3D HPG trend and also output as 2D diagnostic in own right. DO jk = 1, jpkm1 zutrd_hpg(:,:,jk) = zutrd_hpg(:,:,jk) + putrd(:,:) zvtrd_hpg(:,:,jk) = zvtrd_hpg(:,:,jk) + pvtrd(:,:) ENDDO CALL trd_dyn_iom_2d( putrd(:,:), pvtrd(:,:), jpdyn_spg, kt ) CALL trd_dyn_3d( zutrd_hpg, zvtrd_hpg, jpdyn_hpg, kt ) DEALLOCATE( zutrd_hpg, zvtrd_hpg ) CASE( jpdyn_pvo ) ! ! Add 2D PVO trend to 3D PVO trend and also output as diagnostic in own right. DO jk = 1, jpkm1 zutrd_pvo(:,:,jk) = zutrd_pvo(:,:,jk) + putrd(:,:) zvtrd_pvo(:,:,jk) = zvtrd_pvo(:,:,jk) + pvtrd(:,:) ENDDO CALL trd_dyn_iom_2d( putrd, pvtrd, jpdyn_pvo, kt ) CALL trd_dyn_3d( zutrd_pvo, zvtrd_pvo, jpdyn_pvo, kt ) DEALLOCATE( zutrd_pvo, zvtrd_pvo ) CASE( jpdyn_bfr ) ! ! Create 3D BFR trend from 2D field and also output 2D field as diagnostic in own right. ALLOCATE( zutrd_bfr(jpi,jpj,jpk), zvtrd_bfr(jpi,jpj,jpk) ) zutrd_bfr(:,:,:) = 0.0 zvtrd_bfr(:,:,:) = 0.0 DO jk = 1, jpkm1 zutrd_bfr(:,:,jk) = putrd(:,:) zvtrd_bfr(:,:,jk) = pvtrd(:,:) ENDDO CALL trd_dyn_iom_2d( putrd, pvtrd, jpdyn_bfr, kt ) CASE DEFAULT !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ! 2D output of momentum and/or tracers trends using IOM interface !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< IF( ln_dyn_trd ) CALL trd_dyn_iom_2d( putrd, pvtrd, ktrd, kt ) END SELECT !!$ CALLS TO THESE ROUTINES FOR 2D DIAGOSTICS NOT CODED YET !!$ !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< !!$ ! Integral Constraints Properties for momentum and/or tracers trends !!$ !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< !!$ IF( ln_glo_trd ) CALL trd_glo( putrd, pvtrd, ktrd, 'DYN', kt ) !!$ !!$ !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< !!$ ! Kinetic Energy trends !!$ !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !!$ IF( ln_KE_trd ) CALL trd_ken( putrd, pvtrd, ktrd, kt ) !!$ !!$ !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< !!$ ! Vorticity trends !!$ !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !!$ IF( ln_vor_trd ) CALL trd_vor( putrd, pvtrd, ktrd, kt ) !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ! Mixed layer trends for active tracers !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< !!gm IF( ln_dyn_mxl ) CALL trd_mxl_dyn ! END SUBROUTINE trd_dyn_2d SUBROUTINE trd_dyn_iom_3d( putrd, pvtrd, ktrd, kt ) !!--------------------------------------------------------------------- !! *** ROUTINE trd_dyn_iom *** !! !! ** Purpose : output 3D trends using IOM !!---------------------------------------------------------------------- REAL(wp), DIMENSION(:,:,:), INTENT(inout) :: putrd, pvtrd ! U and V trends INTEGER , INTENT(in ) :: ktrd ! trend index INTEGER , INTENT(in ) :: kt ! time step ! INTEGER :: ji, jj, jk ! dummy loop indices INTEGER :: ikbu, ikbv ! local integers REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: z2dx, z2dy ! 2D workspace REAL(wp), ALLOCATABLE, DIMENSION(:,:,:) :: z3dx, z3dy ! 3D workspace !!---------------------------------------------------------------------- ! SELECT CASE( ktrd ) CASE( jpdyn_hpg ) ; CALL iom_put( "utrd_hpg", putrd ) ! hydrostatic pressure gradient CALL iom_put( "vtrd_hpg", pvtrd ) CASE( jpdyn_pvo ) ; CALL iom_put( "utrd_pvo", putrd ) ! planetary vorticity CALL iom_put( "vtrd_pvo", pvtrd ) CASE( jpdyn_rvo ) ; CALL iom_put( "utrd_rvo", putrd ) ! relative vorticity (or metric term) CALL iom_put( "vtrd_rvo", pvtrd ) CASE( jpdyn_keg ) ; CALL iom_put( "utrd_keg", putrd ) ! Kinetic Energy gradient (or had) CALL iom_put( "vtrd_keg", pvtrd ) ALLOCATE( z3dx(jpi,jpj,jpk) , z3dy(jpi,jpj,jpk) ) z3dx(:,:,:) = 0._wp ! U.dxU & V.dyV (approximation) z3dy(:,:,:) = 0._wp DO jk = 1, jpkm1 ! no mask as un,vn are masked DO jj = 2, jpjm1 DO ji = 2, jpim1 z3dx(ji,jj,jk) = un(ji,jj,jk) * ( un(ji+1,jj,jk) - un(ji-1,jj,jk) ) / ( 2._wp * e1u(ji,jj) ) z3dy(ji,jj,jk) = vn(ji,jj,jk) * ( vn(ji,jj+1,jk) - vn(ji,jj-1,jk) ) / ( 2._wp * e2v(ji,jj) ) END DO END DO END DO CALL lbc_lnk_multi( 'trddyn', z3dx, 'U', -1., z3dy, 'V', -1. ) CALL iom_put( "utrd_udx", z3dx ) CALL iom_put( "vtrd_vdy", z3dy ) DEALLOCATE( z3dx , z3dy ) CASE( jpdyn_zad ) ; CALL iom_put( "utrd_zad", putrd ) ! vertical advection CALL iom_put( "vtrd_zad", pvtrd ) CASE( jpdyn_ldf ) ; CALL iom_put( "utrd_ldf", putrd ) ! lateral diffusion CALL iom_put( "vtrd_ldf", pvtrd ) CASE( jpdyn_zdf ) ; CALL iom_put( "utrd_zdf", putrd ) ! vertical diffusion CALL iom_put( "vtrd_zdf", pvtrd ) ! ! ! wind stress trends ALLOCATE( z2dx(jpi,jpj) , z2dy(jpi,jpj) ) z2dx(:,:) = ( utau_b(:,:) + utau(:,:) ) / ( e3u_n(:,:,1) * rau0 ) z2dy(:,:) = ( vtau_b(:,:) + vtau(:,:) ) / ( e3v_n(:,:,1) * rau0 ) CALL iom_put( "utrd_tau", z2dx ) CALL iom_put( "vtrd_tau", z2dy ) DEALLOCATE( z2dx , z2dy ) CASE( jpdyn_bfr ) ; CALL iom_put( "utrd_bfr", putrd ) ! bottom friction (explicit case) CALL iom_put( "vtrd_bfr", pvtrd ) CASE( jpdyn_bfri) ; CALL iom_put( "utrd_bfri", putrd ) ! bottom friction (implicit case) CALL iom_put( "vtrd_bfri", pvtrd ) CASE( jpdyn_atf ) ; CALL iom_put( "utrd_atf", putrd ) ! asselin filter trends CALL iom_put( "vtrd_atf", pvtrd ) END SELECT ! END SUBROUTINE trd_dyn_iom_3d SUBROUTINE trd_dyn_iom_2d( putrd, pvtrd, ktrd, kt ) !!--------------------------------------------------------------------- !! *** ROUTINE trd_dyn_iom *** !! !! ** Purpose : output 2D trends using IOM !!---------------------------------------------------------------------- REAL(wp), DIMENSION(:,:), INTENT(inout) :: putrd, pvtrd ! U and V trends INTEGER , INTENT(in ) :: ktrd ! trend index INTEGER , INTENT(in ) :: kt ! time step ! INTEGER :: ji, jj, jk ! dummy loop indices INTEGER :: ikbu, ikbv ! local integers REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: z2dx, z2dy ! 2D workspace REAL(wp), ALLOCATABLE, DIMENSION(:,:,:) :: z3dx, z3dy ! 3D workspace !!---------------------------------------------------------------------- ! SELECT CASE( ktrd ) CASE( jpdyn_spg ) ; CALL iom_put( "utrd_spg2d", putrd ) ! surface pressure gradient CALL iom_put( "vtrd_spg2d", pvtrd ) CASE( jpdyn_pvo ) ; CALL iom_put( "utrd_pvo2d", putrd ) ! planetary vorticity (barotropic part) CALL iom_put( "vtrd_pvo2d", pvtrd ) CASE( jpdyn_hpg_corr ) ; CALL iom_put( "utrd_hpg_corr", putrd ) ! horizontal pressure gradient correction CALL iom_put( "vtrd_hpg_corr", pvtrd ) CASE( jpdyn_pvo_corr ) ; CALL iom_put( "utrd_pvo_corr", putrd ) ! planetary vorticity correction CALL iom_put( "vtrd_pvo_corr", pvtrd ) CASE( jpdyn_bfr ) ; CALL iom_put( "utrd_bfr2d", putrd ) ! bottom friction due to barotropic currents CALL iom_put( "vtrd_bfr2d", pvtrd ) END SELECT ! END SUBROUTINE trd_dyn_iom_2d !!====================================================================== END MODULE trddyn