!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| module mix_submeso 1,19 !BOP ! !MODULE: mix_submeso ! !DESCRIPTION: ! This module contains routines for computing submesoscale mixing ! using the Fox-Kemper, Ferrari, and Hallberg parameterization ! for restratification by mixed layer eddies. ! !REVISION HISTORY: ! SVN:$Id: mix_submeso.F90 ! !USES: use POP_KindsMod use POP_IOUnitsMod use POP_ErrorMod use kinds_mod use blocks use domain use constants use broadcast use grid use io use vertical_mix use vmix_kpp use time_management use tavg use exit_mod use registry use communicate use hmix_gm_submeso_share #ifdef CCSMCOUPLED use shr_sys_mod #endif implicit none private save ! !PUBLIC MEMBER FUNCTIONS: public :: init_submeso, & submeso_sf, & submeso_flux !EOP !BOC !----------------------------------------------------------------------- ! ! variables to save from one call to next ! !----------------------------------------------------------------------- integer (int_kind), parameter :: & ktp = 1, kbt = 2 ! refer to the top and bottom halves of a ! grid cell, respectively real (r8), dimension(:,:,:,:,:,:), allocatable, public :: & SF_SUBM_X, & ! components of the submesoscale SF_SUBM_Y ! streamfunction real (r8), dimension(:,:,:,:), allocatable :: & FZTOP_SUBM !----------------------------------------------------------------------- ! ! tavg ids for tavg diagnostics related to submesoscale mixing. ! Zonal and meridional refer here to logical space only. ! !----------------------------------------------------------------------- integer (int_kind) :: & tavg_USUBM, & ! zonal submeso velocity tavg_VSUBM, & ! meridional submeso velocity tavg_WSUBM, & ! vertical submeso velocity tavg_ADVT_SUBM, & ! vertically-integrated T submeso ! advection tendency tavg_ADVS_SUBM, & ! vertically-integrated S submeso ! advection tendency tavg_VNT_SUBM, & ! heat flux tendency in grid-y direction ! due to submeso velocity tavg_VNS_SUBM, & ! salt flux tendency in grid-y direction ! due to submeso velocity tavg_HLS_SUBM ! horizontal length scale used in horizontal ! buoyancy gradient scaling in submeso real (r8), dimension(:,:,:), allocatable :: & TIME_SCALE ! time scale used in horizontal length scale ! calculation real (r8) :: & max_hor_grid_scale ! maximum horizontal grid scale allowed !----------------------------------------------------------------------- ! ! namelist variables ! !----------------------------------------------------------------------- logical (log_kind) :: & luse_const_horiz_len_scale ! if .true., then use a constant ! horizontal length scale given by ! hor_length_scale, otherwise the ! horizontal length scale varies both ! in space and time real (r8) :: & efficiency_factor, & ! 0.06 <= efficiency factor <= 0.08 time_scale_constant, & ! 1 day <= time scale constant <= 1 week hor_length_scale ! constant horizontal length scale used ! if luse_const_horiz_len_scale is true. ! if luse_const_horiz_len_scale is false, ! then hor_length_scale is used as the ! lower limit. !----------------------------------------------------------------------- ! ! misc module variables ! !----------------------------------------------------------------------- real (r8) :: & sqrt_grav ! sqrt(grav) !EOC !*********************************************************************** contains !*********************************************************************** !BOP ! !IROUTINE: init_submeso ! !INTERFACE: subroutine init_submeso 1,17 ! !DESCRIPTION: ! Initializes various submesoscale mixing options and allocates necessary ! space. Also computes some time-independent arrays. ! ! !REVISION HISTORY: ! same as module !EOP !BOC !----------------------------------------------------------------------- ! ! local variables and namelist ! !----------------------------------------------------------------------- integer (int_kind) :: & nml_error, & ! error flag for namelist iblock ! block index namelist /mix_submeso_nml/ efficiency_factor, & time_scale_constant, & luse_const_horiz_len_scale, & hor_length_scale !----------------------------------------------------------------------- ! ! register init_submeso ! !----------------------------------------------------------------------- call register_string ('init_submeso') !----------------------------------------------------------------------- ! ! default namelist values ! !----------------------------------------------------------------------- efficiency_factor = 0.07_r8 time_scale_constant = 3.456e5_r8 ! 4 days, in seconds luse_const_horiz_len_scale = .false. hor_length_scale = 5.0e5_r8 ! 5 km max_hor_grid_scale = 111.0e5_r8 ! about 1 degree if (my_task == master_task) then open (nml_in, file=nml_filename, status='old', iostat=nml_error) if (nml_error /= 0) then nml_error = -1 else nml_error = 1 endif do while (nml_error > 0) read(nml_in, nml=mix_submeso_nml, iostat=nml_error) enddo if (nml_error == 0) close(nml_in) endif call broadcast_scalar(nml_error, master_task) if (nml_error /= 0) then call exit_POP(sigAbort, 'ERROR reading mix_submeso_nml') endif if (my_task == master_task) then write(stdout,*) ' ' write(stdout,*) ' Document Namelist Parameters:' write(stdout,*) ' ============================ ' write(stdout,*) ' ' write(stdout, mix_submeso_nml) write(stdout,*) ' ' write(stdout,*) ' Submesoscale mixing options:' write(stdout,'(a21,1pe13.6)') ' efficiency factor = ', efficiency_factor write(stdout,'(a23,1pe13.6)') ' time scale constant = ', time_scale_constant if ( luse_const_horiz_len_scale ) then write(stdout,'(a45,1pe13.6)') & ' using a constant horizontal length scale of ', hor_length_scale else write(stdout,'(a54)') ' horizontal length scale varies both in space and time' endif call POP_IOUnitsFlush(POP_stdout) ; call POP_IOUnitsFlush(stdout) endif call broadcast_scalar (efficiency_factor, master_task) call broadcast_scalar (time_scale_constant, master_task) call broadcast_scalar (luse_const_horiz_len_scale, master_task) call broadcast_scalar (hor_length_scale, master_task) !----------------------------------------------------------------------- ! ! define scalar constants ! !----------------------------------------------------------------------- sqrt_grav = sqrt(grav) !----------------------------------------------------------------------- ! ! allocate necessary arrays ! !----------------------------------------------------------------------- allocate (SF_SUBM_X(nx_block,ny_block,2,2,km,nblocks_clinic), & SF_SUBM_Y(nx_block,ny_block,2,2,km,nblocks_clinic)) allocate (TIME_SCALE(nx_block,ny_block,nblocks_clinic)) allocate (FZTOP_SUBM(nx_block,ny_block,nt,nblocks_clinic)) SF_SUBM_X = c0 SF_SUBM_Y = c0 TIME_SCALE = c0 FZTOP_SUBM = c0 !----------------------------------------------------------------------- ! ! initialize various time-independent arrays ! !----------------------------------------------------------------------- do iblock = 1,nblocks_clinic TIME_SCALE(:,:,iblock) = c1 / sqrt( FCORT(:,:,iblock)**2 & + c1 / (time_scale_constant**2) ) enddo !----------------------------------------------------------------------- ! ! define tavg fields related to the submesoscale parameterization ! !----------------------------------------------------------------------- call define_tavg_field (tavg_USUBM, 'USUBM', 3, & long_name='Submeso velocity in grid-x direction (diagnostic)', & units='cm/s', grid_loc='3211', & coordinates='ULONG TLAT z_t time') call define_tavg_field (tavg_VSUBM, 'VSUBM', 3, & long_name='Submeso velocity in grid-y direction (diagnostic)', & units='cm/s', grid_loc='3121', & coordinates='TLONG ULAT z_t time') call define_tavg_field (tavg_WSUBM, 'WSUBM', 3, & long_name='Vertical submeso velocity (diagnostic)', & units='cm/s', grid_loc='3112', & coordinates='TLONG TLAT z_w time') call define_tavg_field (tavg_HLS_SUBM, 'HLS_SUBM', 2, & long_name='Horizontal length scale used in submeso', & units='cm', grid_loc='2110', & coordinates='TLONG TLAT time') call define_tavg_field (tavg_ADVT_SUBM, 'ADVT_SUBM', 2, & long_name='Vertically-Integrated T submeso Advection Tendency (diagnostic)', & units='cm degC/s', grid_loc='2110', & coordinates='TLONG TLAT time') call define_tavg_field (tavg_ADVS_SUBM, 'ADVS_SUBM', 2, & long_name='Vertically-Integrated S submeso Advection Tendency (diagnostic)', & scale_factor=1000.0_rtavg, & units='cm gram/kilogram/s', grid_loc='2110', & coordinates='TLONG TLAT time') call define_tavg_field (tavg_VNT_SUBM, 'VNT_SUBM', 3, & long_name='Heat Flux Tendency in grid-y Dir due to submeso Vel (diagnostic)', & units='degC/s', grid_loc='3121', & coordinates='TLONG ULAT z_t time') call define_tavg_field (tavg_VNS_SUBM, 'VNS_SUBM', 3, & long_name='Salt Flux Tendency in grid-y Dir due to submeso Vel (diagnostic)', & scale_factor=1000.0_rtavg, & units='gram/kilogram/s', grid_loc='3121', & coordinates='TLONG ULAT z_t time') !----------------------------------------------------------------------- !EOC end subroutine init_submeso !*********************************************************************** !BOP ! !IROUTINE: submeso_sf ! !INTERFACE: subroutine submeso_sf ( TMIX, this_block ) 1,28 ! !DESCRIPTION: ! The Fox-Kemper, Ferrari, and Hallberg [2008] submesoscale parameterization ! for restratification by mixed layer eddies. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: type (block), intent(in) :: & this_block ! block info for this sub block real (r8), dimension(nx_block,ny_block,km,nt), intent(in) :: & TMIX ! tracers at all vertical levels ! at mixing time level !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (int_kind) :: & i, j, k, kk, & ! dummy loop counters kp1, & bid, & ! local block address for this sub block tavg_stream ! temporary stream id real (r8), dimension(nx_block,ny_block) :: & ML_DEPTH, & ! mixed layer depth HLS, & ! horizontal length scale WORK1, WORK2, & ! work arrays WORK3, & USMT, VSMT, & ! arrays for submeso velocity computation USMB, VSMB, & U_SUBM, V_SUBM, & WBOT_SUBM, & WTOP_SUBM real (r8), dimension(2) :: & reference_depth logical (log_kind), dimension(nx_block,ny_block) :: & CONTINUE_INTEGRAL ! flag real (r8), dimension(nx_block,ny_block,2) :: & BX_VERT_AVG, & ! horizontal buoyancy differences vertically BY_VERT_AVG ! averaged within the mixed layer real (r8) :: & zw_top, factor !----------------------------------------------------------------------- ! ! initialize various quantities ! !----------------------------------------------------------------------- bid = this_block%local_id WORK1 = c0 WORK2 = c0 WORK3 = c0 HLS = c0 USMT = c0 USMB = c0 VSMT = c0 VSMB = c0 U_SUBM = c0 V_SUBM = c0 WTOP_SUBM = c0 WBOT_SUBM = c0 BX_VERT_AVG = c0 BY_VERT_AVG = c0 SF_SUBM_X(:,:,:,:,:,bid) = c0 SF_SUBM_Y(:,:,:,:,:,bid) = c0 ML_DEPTH = zw(1) if ( vmix_itype == vmix_type_kpp ) & ML_DEPTH(:,:) = HMXL(:,:,bid) CONTINUE_INTEGRAL = .true. where ( KMT(:,:,bid) == 0 ) CONTINUE_INTEGRAL = .false. endwhere !----------------------------------------------------------------------- ! ! compute vertical averages of horizontal buoyancy differences ! within the mixed layer ! !----------------------------------------------------------------------- do k=1,km zw_top = c0 if ( k > 1 ) zw_top = zw(k-1) WORK3 = c0 where ( CONTINUE_INTEGRAL .and. ML_DEPTH > zw(k) ) WORK3 = dz(k) endwhere where ( CONTINUE_INTEGRAL .and. ML_DEPTH <= zw(k) & .and. ML_DEPTH > zw_top ) WORK3 = ML_DEPTH - zw_top endwhere where ( CONTINUE_INTEGRAL ) BX_VERT_AVG(:,:,1) = BX_VERT_AVG(:,:,1) & + RX(:,:,1,k,bid) * WORK3 BX_VERT_AVG(:,:,2) = BX_VERT_AVG(:,:,2) & + RX(:,:,2,k,bid) * WORK3 BY_VERT_AVG(:,:,1) = BY_VERT_AVG(:,:,1) & + RY(:,:,1,k,bid) * WORK3 BY_VERT_AVG(:,:,2) = BY_VERT_AVG(:,:,2) & + RY(:,:,2,k,bid) * WORK3 endwhere where ( CONTINUE_INTEGRAL .and. ML_DEPTH <= zw(k) & .and. ML_DEPTH > zw_top ) CONTINUE_INTEGRAL = .false. endwhere enddo #ifdef CCSMCOUPLED if ( any(CONTINUE_INTEGRAL) ) then call shr_sys_abort ('Incorrect mixed layer depth in submeso subroutine (I)') endif #endif where ( KMT(:,:,bid) > 0 ) BX_VERT_AVG(:,:,1) = - grav * BX_VERT_AVG(:,:,1) / ML_DEPTH BX_VERT_AVG(:,:,2) = - grav * BX_VERT_AVG(:,:,2) / ML_DEPTH BY_VERT_AVG(:,:,1) = - grav * BY_VERT_AVG(:,:,1) / ML_DEPTH BY_VERT_AVG(:,:,2) = - grav * BY_VERT_AVG(:,:,2) / ML_DEPTH endwhere !----------------------------------------------------------------------- ! ! compute horizontal length scale if necessary ! !----------------------------------------------------------------------- if ( luse_const_horiz_len_scale ) then where ( KMT(:,:,bid) > 0 ) HLS = hor_length_scale endwhere else WORK1 = c0 where ( KMT(:,:,bid) > 0 ) WORK1 = sqrt( p5 * ( & ( BX_VERT_AVG(:,:,1)**2 + BX_VERT_AVG(:,:,2)**2 ) & / DXT(:,:,bid)**2 & + ( BY_VERT_AVG(:,:,1)**2 + BY_VERT_AVG(:,:,2)**2 ) & / DYT(:,:,bid)**2 ) ) WORK1 = WORK1 * ML_DEPTH * (TIME_SCALE(:,:,bid)**2) endwhere CONTINUE_INTEGRAL = .true. where ( KMT(:,:,bid) == 0 ) CONTINUE_INTEGRAL = .false. endwhere WORK2 = c0 do k=2,km WORK3 = c0 where ( CONTINUE_INTEGRAL .and. ML_DEPTH > zt(k) ) WORK3 = dzw(k-1) endwhere where ( CONTINUE_INTEGRAL .and. ML_DEPTH <= zt(k) & .and. ML_DEPTH >= zt(k-1) ) WORK3 = ( (ML_DEPTH - zt(k-1))**2 ) * dzwr(k-1) endwhere where ( CONTINUE_INTEGRAL ) WORK2 = WORK2 + sqrt(-RZ_SAVE(:,:,k,bid) * WORK3) endwhere where ( CONTINUE_INTEGRAL .and. ML_DEPTH <= zt(k) & .and. ML_DEPTH >= zt(k-1) ) CONTINUE_INTEGRAL = .false. endwhere enddo #ifdef CCSMCOUPLED if ( any(CONTINUE_INTEGRAL) ) then call shr_sys_abort ('Incorrect mixed layer depth in submeso subroutine (II)') endif #endif where ( KMT(:,:,bid) > 0 ) WORK2 = sqrt_grav * WORK2 * TIME_SCALE(:,:,bid) HLS = max ( WORK1, WORK2, hor_length_scale ) endwhere endif !----------------------------------------------------------------------- ! ! compute streamfunction due to submesoscale parameterization ! !----------------------------------------------------------------------- do k=1,km reference_depth(ktp) = zt(k) - p25 * dz(k) reference_depth(kbt) = zt(k) + p25 * dz(k) do kk=ktp,kbt where ( reference_depth(kk) < ML_DEPTH .and. & KMT(:,:,bid) >= k ) WORK3 = ( c1 - ( c2 * reference_depth(kk) / ML_DEPTH ) )**2 WORK2 = ( c1 - WORK3 ) & * ( c1 + ( 5.0_r8 / 21.0_r8 ) * WORK3 ) WORK1 = efficiency_factor * (ML_DEPTH**2) * WORK2 & * TIME_SCALE(:,:,bid) / HLS ! in the following negative sign is omitted to be consistent with ! the GM implementation in hmix_gm subroutine. also, DXT and ! DYT usage is approximate. SF_SUBM_X(:,:,1,kk,k,bid) = WORK1 * BX_VERT_AVG(:,:,1) & * min(DXT(:,:,bid),max_hor_grid_scale) SF_SUBM_X(:,:,2,kk,k,bid) = WORK1 * BX_VERT_AVG(:,:,2) & * min(DXT(:,:,bid),max_hor_grid_scale) SF_SUBM_Y(:,:,1,kk,k,bid) = WORK1 * BY_VERT_AVG(:,:,1) & * min(DYT(:,:,bid),max_hor_grid_scale) SF_SUBM_Y(:,:,2,kk,k,bid) = WORK1 * BY_VERT_AVG(:,:,2) & * min(DYT(:,:,bid),max_hor_grid_scale) endwhere enddo enddo USMT = c0 VSMT = c0 do k=1,km !----------------------------------------------------------------------- ! ! diagnostic computation of the submeso velocities ! !----------------------------------------------------------------------- kp1 = k+1 factor = c1 if ( k == km ) then kp1 = k factor = c0 endif do j=1,ny_block-1 do i=1,nx_block-1 WORK1(i,j) = ( SF_SUBM_X(i ,j,1,kbt,k, bid) & + factor * SF_SUBM_X(i ,j,1,ktp,kp1,bid) & + SF_SUBM_X(i+1,j,2,kbt,k, bid) & + factor * SF_SUBM_X(i+1,j,2,ktp,kp1,bid) ) & * p25 * HYX(i,j,bid) WORK2(i,j) = ( SF_SUBM_Y(i,j ,1,kbt,k, bid) & + factor * SF_SUBM_Y(i,j ,1,ktp,kp1,bid) & + SF_SUBM_Y(i,j+1,2,kbt,k, bid) & + factor * SF_SUBM_Y(i,j+1,2,ktp,kp1,bid) ) & * p25 * HXY(i,j,bid) enddo enddo USMB = merge( WORK1, c0, k < KMT(:,:,bid) .and. k < KMTE(:,:,bid) ) VSMB = merge( WORK2, c0, k < KMT(:,:,bid) .and. k < KMTN(:,:,bid) ) WORK1 = merge( USMT - USMB, c0, k <= KMT(:,:,bid) & .and. k <= KMTE(:,:,bid) ) WORK2 = merge( VSMT - VSMB, c0, k <= KMT(:,:,bid) & .and. k <= KMTN(:,:,bid) ) U_SUBM = WORK1 * dzr(k) / HTE(:,:,bid) V_SUBM = WORK2 * dzr(k) / HTN(:,:,bid) do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie if ( k < KMT(i,j,bid) .and. ( zw(k) < max( ML_DEPTH(i,j), & ML_DEPTH(i+1,j), ML_DEPTH(i-1,j), ML_DEPTH(i,j+1), & ML_DEPTH(i,j-1) ) ) ) then WBOT_SUBM(i,j) = WTOP_SUBM(i,j) & + TAREA_R(i,j,bid) & * ( WORK1(i,j) - WORK1(i-1,j) & + WORK2(i,j) - WORK2(i,j-1) ) else WBOT_SUBM(i,j) = c0 endif enddo enddo !----------------------------------------------------------------------- ! ! accumulate time average if necessary ! !----------------------------------------------------------------------- if ( mix_pass /= 1 ) then tavg_stream = tavg_in_which_stream(tavg_HLS_SUBM) if ( ltavg_on(tavg_stream) .and. tavg_requested(tavg_HLS_SUBM) .and. k == 1 ) then call accumulate_tavg_field (HLS, tavg_HLS_SUBM, bid, 1) endif tavg_stream = tavg_in_which_stream(tavg_USUBM) if ( ltavg_on(tavg_stream) .and. tavg_requested(tavg_USUBM) ) then call accumulate_tavg_field (U_SUBM, tavg_USUBM, bid, k) endif tavg_stream = tavg_in_which_stream(tavg_VSUBM) if ( ltavg_on(tavg_stream) .and. tavg_requested(tavg_VSUBM) ) then call accumulate_tavg_field (V_SUBM, tavg_VSUBM, bid, k) endif tavg_stream = tavg_in_which_stream(tavg_WSUBM) if ( ltavg_on(tavg_stream) .and. tavg_requested(tavg_WSUBM) ) then call accumulate_tavg_field (WTOP_SUBM, tavg_WSUBM, bid, k) endif tavg_stream = tavg_in_which_stream(tavg_ADVT_SUBM) if ( ltavg_on(tavg_stream) .and. tavg_requested(tavg_ADVT_SUBM) ) then WORK1 = p5 * HTE(:,:,bid) * U_SUBM * ( TMIX(:,:,k,1) & + eoshift(TMIX(:,:,k,1), dim=1, shift=1) ) WORK2 = eoshift(WORK1, dim=1, shift=-1) WORK3 = WORK1 - WORK2 WORK1 = p5 * HTN(:,:,bid) * V_SUBM * ( TMIX(:,:,k,1) & + eoshift(TMIX(:,:,k,1), dim=2, shift=1) ) WORK2 = eoshift(WORK1, dim=2, shift=-1) WORK3 = WORK3 + WORK1 - WORK2 WORK1 = c0 do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie if ( k <= KMT(i,j,bid) ) then WORK1(i,j) = - dz(k) * TAREA_R(i,j,bid) * WORK3(i,j) endif enddo enddo call accumulate_tavg_field (WORK1, tavg_ADVT_SUBM, bid, k) endif tavg_stream = tavg_in_which_stream(tavg_ADVS_SUBM) if ( ltavg_on(tavg_stream) .and. tavg_requested(tavg_ADVS_SUBM) ) then WORK1 = p5 * HTE(:,:,bid) * U_SUBM * ( TMIX(:,:,k,2) & + eoshift(TMIX(:,:,k,2), dim=1, shift=1) ) WORK2 = eoshift(WORK1, dim=1, shift=-1) WORK3 = WORK1 - WORK2 WORK1 = p5 * HTN(:,:,bid) * V_SUBM * ( TMIX(:,:,k,2) & + eoshift(TMIX(:,:,k,2), dim=2, shift=1) ) WORK2 = eoshift(WORK1, dim=2, shift=-1) WORK3 = WORK3 + WORK1 - WORK2 WORK1 = c0 do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie if ( k <= KMT(i,j,bid) ) then WORK1(i,j) = - dz(k) * TAREA_R(i,j,bid) * WORK3(i,j) endif enddo enddo call accumulate_tavg_field (WORK1, tavg_ADVS_SUBM, bid, k) endif if ( tavg_requested(tavg_VNT_SUBM) .or. & tavg_requested(tavg_VNS_SUBM) ) then WORK1 = p5 * V_SUBM * HTN(:,:,bid) * TAREA_R(:,:,bid) tavg_stream = tavg_in_which_stream(tavg_VNT_SUBM) if ( ltavg_on(tavg_stream) .and. tavg_requested(tavg_VNT_SUBM) ) then WORK2 = WORK1 * ( TMIX(:,:,k,1) & + eoshift(TMIX(:,:,k,1), dim=2, shift=1) ) call accumulate_tavg_field (WORK2, tavg_VNT_SUBM, bid, k) endif tavg_stream = tavg_in_which_stream(tavg_VNS_SUBM) if ( ltavg_on(tavg_stream) .and. tavg_requested(tavg_VNS_SUBM) ) then WORK2 = WORK1 * ( TMIX(:,:,k,2) & + eoshift(TMIX(:,:,k,2), dim=2, shift=1) ) call accumulate_tavg_field (WORK2, tavg_VNS_SUBM, bid, k) endif endif endif ! mix_pass ne 1 !----------------------------------------------------------------------- ! ! update remaining bottom-face fields to top-face fields for next pass ! !----------------------------------------------------------------------- USMT = USMB VSMT = VSMB WTOP_SUBM = WBOT_SUBM enddo !----------------------------------------------------------------------- !EOC end subroutine submeso_sf !*********************************************************************** ! !IROUTINE: submeso_flux ! !INTERFACE: subroutine submeso_flux (k, GTK, TMIX, tavg_HDIFE_TRACER, & 1,9 tavg_HDIFN_TRACER, tavg_HDIFB_TRACER, this_block) ! !DESCRIPTION: ! Computes the fluxes due to submesoscale mixing of tracers ! !INPUT PARAMETERS: integer (int_kind), intent(in) :: k ! depth level index type (block), intent(in) :: & this_block ! block info for this sub block real (r8), dimension(nx_block,ny_block,km,nt), intent(in) :: & TMIX ! tracers at all vertical levels ! at mixing time level integer (int_kind), dimension(nt), intent(in) :: & tavg_HDIFE_TRACER, &! tavg id for east face diffusive flux of tracer tavg_HDIFN_TRACER, &! tavg id for north face diffusive flux of tracer tavg_HDIFB_TRACER ! tavg id for bottom face diffusive flux of tracer ! !OUTPUT PARAMETERS: real (r8), dimension(nx_block,ny_block,nt), intent(out) :: & GTK ! submesoscale tracer flux at level k !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (int_kind), parameter :: & ieast = 1, iwest = 2, & jnorth = 1, jsouth = 2 integer (int_kind) :: & i,j,n, &!dummy loop counters bid, &! local block address for this sub block kp1 real (r8) :: & fz, factor real (r8), dimension(nx_block,ny_block) :: & CX, CY, & WORK1, WORK2, &! local work space KMASK ! ocean mask real (r8), dimension(nx_block,ny_block,nt) :: & FX, FY ! fluxes across east, north faces bid = this_block%local_id if ( k == 1) FZTOP_SUBM(:,:,:,bid) = c0 ! zero flux B.C. at the surface CX = merge(HYX(:,:,bid)*p25, c0, (k <= KMT (:,:,bid)) & .and. (k <= KMTE(:,:,bid))) CY = merge(HXY(:,:,bid)*p25, c0, (k <= KMT (:,:,bid)) & .and. (k <= KMTN(:,:,bid))) KMASK = merge(c1, c0, k < KMT(:,:,bid)) kp1 = k + 1 if ( k == km ) kp1 = k if ( k < km ) then factor = c1 else factor = c0 endif do n = 1,nt if (.not.registry_match('init_gm')) then if (n > 2 .and. k < km) & TZ(:,:,k+1,n,bid) = TMIX(:,:,k ,n) - TMIX(:,:,k+1,n) endif do j=1,ny_block do i=1,nx_block-1 FX(i,j,n) = CX(i,j) & * ( SF_SUBM_X(i ,j,ieast,ktp,k,bid) * TZ(i,j,k,n,bid) & + SF_SUBM_X(i ,j,ieast,kbt,k,bid) * TZ(i,j,kp1,n,bid) & + SF_SUBM_X(i+1,j,iwest,ktp,k,bid) * TZ(i+1,j,k,n,bid) & + SF_SUBM_X(i+1,j,iwest,kbt,k,bid) * TZ(i+1,j,kp1,n,bid) ) enddo enddo end do do n = 1,nt do j=1,ny_block-1 do i=1,nx_block FY(i,j,n) = CY(i,j) & * ( SF_SUBM_Y(i,j ,jnorth,ktp,k,bid) * TZ(i,j,k,n,bid) & + SF_SUBM_Y(i,j ,jnorth,kbt,k,bid) * TZ(i,j,kp1,n,bid) & + SF_SUBM_Y(i,j+1,jsouth,ktp,k,bid) * TZ(i,j+1,k,n,bid) & + SF_SUBM_Y(i,j+1,jsouth,kbt,k,bid) * TZ(i,j+1,kp1,n,bid) ) enddo enddo end do ! zero halo regions so accumulate_tavg_field calls do not trap WORK1 = c0 WORK2 = c0 do n = 1,nt !----------------------------------------------------------------------- ! ! calculate vertical submesoscale fluxes thru horizontal faces of T-cell ! !----------------------------------------------------------------------- GTK(:,:,n) = c0 if ( k < km ) then do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie WORK1(i,j) = SF_SUBM_X(i ,j ,ieast ,kbt,k ,bid) & * HYX(i ,j ,bid) * TX(i ,j ,k ,n,bid) & + SF_SUBM_Y(i ,j ,jnorth,kbt,k ,bid) & * HXY(i ,j ,bid) * TY(i ,j ,k ,n,bid) & + SF_SUBM_X(i ,j ,iwest ,kbt,k ,bid) & * HYX(i-1,j ,bid) * TX(i-1,j ,k ,n,bid) & + SF_SUBM_Y(i ,j ,jsouth,kbt,k ,bid) & * HXY(i ,j-1,bid) * TY(i ,j-1,k ,n,bid) enddo enddo do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie WORK2(i,j) = factor & * ( SF_SUBM_X(i ,j ,ieast ,ktp,kp1,bid) & * HYX(i ,j ,bid) * TX(i ,j ,kp1,n,bid) & + SF_SUBM_Y(i ,j ,jnorth,ktp,kp1,bid) & * HXY(i ,j ,bid) * TY(i ,j ,kp1,n,bid) & + SF_SUBM_X(i ,j ,iwest ,ktp,kp1,bid) & * HYX(i-1,j ,bid) * TX(i-1,j ,kp1,n,bid) & + SF_SUBM_Y(i ,j ,jsouth,ktp,kp1,bid) & * HXY(i ,j-1,bid) * TY(i ,j-1,kp1,n,bid) ) enddo enddo do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie fz = -KMASK(i,j) * p25 & * (WORK1(i,j) + WORK2(i,j)) GTK(i,j,n) = ( FX(i,j,n) - FX(i-1,j,n) & + FY(i,j,n) - FY(i,j-1,n) & + FZTOP_SUBM(i,j,n,bid) - fz )*dzr(k)*TAREA_R(i,j,bid) FZTOP_SUBM(i,j,n,bid) = fz enddo enddo else ! k = km do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie GTK(i,j,n) = ( FX(i,j,n) - FX(i-1,j,n) & + FY(i,j,n) - FY(i,j-1,n) & + FZTOP_SUBM(i,j,n,bid) )*dzr(k)*TAREA_R(i,j,bid) FZTOP_SUBM(i,j,n,bid) = c0 enddo enddo endif !----------------------------------------------------------------------- ! ! accumulate time average if necessary ! !----------------------------------------------------------------------- if ( mix_pass /= 1 ) then if (tavg_requested(tavg_HDIFE_TRACER(n))) then if (ltavg_on(tavg_in_which_stream(tavg_HDIFE_TRACER(n)))) then do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie WORK1(i,j) = FX(i,j,n)*dzr(k)*TAREA_R(i,j,bid) enddo enddo call accumulate_tavg_field(WORK1,tavg_HDIFE_TRACER(n),bid,k) endif endif if (tavg_requested(tavg_HDIFN_TRACER(n))) then if (ltavg_on(tavg_in_which_stream(tavg_HDIFN_TRACER(n)))) then do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie WORK1(i,j) = FY(i,j,n)*dzr(k)*TAREA_R(i,j,bid) enddo enddo call accumulate_tavg_field(WORK1,tavg_HDIFN_TRACER(n),bid,k) endif endif if (tavg_requested(tavg_HDIFB_TRACER(n))) then if (ltavg_on(tavg_in_which_stream(tavg_HDIFB_TRACER(n)))) then do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie WORK1(i,j) = FZTOP_SUBM(i,j,n,bid)*dzr(k)*TAREA_R(i,j,bid) enddo enddo call accumulate_tavg_field(WORK1,tavg_HDIFB_TRACER(n),bid,k) endif endif endif ! mix_pass ne 1 !----------------------------------------------------------------------- ! ! end of tracer loop ! !----------------------------------------------------------------------- enddo !ends the do n loop !----------------------------------------------------------------------- end subroutine submeso_flux !*********************************************************************** end module mix_submeso !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||