!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! !!
!! GNU General Public License !!
!! !!
!! This file is part of the Flexible Modeling System (FMS). !!
!! !!
!! FMS is free software; you can redistribute it and/or modify !!
!! it and are expected to follow the terms of the GNU General Public !!
!! License as published by the Free Software Foundation. !!
!! !!
!! FMS is distributed in the hope that it will be useful, !!
!! but WITHOUT ANY WARRANTY; without even the implied warranty of !!
!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !!
!! GNU General Public License for more details. !!
!! !!
!! You should have received a copy of the GNU General Public License !!
!! along with FMS; if not, write to: !!
!! Free Software Foundation, Inc. !!
!! 59 Temple Place, Suite 330 !!
!! Boston, MA 02111-1307 USA !!
!! or see: !!
!! http://www.gnu.org/licenses/gpl.txt !!
!! !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module ocean_overflow_mod
!
! S.M. Griffies
!
!
! Michael Bates
!
!
!
! Tracer source from discharging dense shallow water into the abyss
! at the parcel's depth of neutral buoyancy.
!
!
!
! Tracer source from discharging dense shallow water into the abyss
! at the parcel's depth of neutral buoyancy. Follow the approach
! of Campin and Goosse (1999), as well as modifications.
!
!
!
!
!
! Campin and Goosse (1999): Parameterization of density-driven downsloping flow
! for a coarse-resolution model in z-coordinate", Tellus 51A, pages 412-430
!
!
!
! S.M. Griffies, M.J. Harrison, R. C. Pacanowski, and A. Rosati
! A Technical Guide to MOM4 (2003)
! NOAA/Geophysical Fluid Dynamics Laboratory
!
!
!
! S.M. Griffies, Elements of mom4p1 (2006)
! NOAA/Geophysical Fluid Dynamics Laboratory
!
!
!
!
!
!
! For using this module. Default is false.
!
!
! For debugging
!
!
!
! Dissipation rate for the bottom friction. Campin and Goosse
! suggest overflow_mu=10^-4
!
!
! Fraction of a grid cell participating in the overflow process.
! Campin and Goosse suggest overflow_delta=1/3.
!
!
! Maximum downslope speed.
!
!
! Set true to do bitwise exact global sum. When it is false, the global
! sum will be non-bitwise_exact, but will significantly increase efficiency.
! The default value is false.
!
!
!
! Set true to remove the Campin and Goose return flow "piping".
! Default no_return_flow=.false. to recover the standard approach from
! Campin and Goose.
!
!
!
use constants_mod, only: epsln, grav
use diag_manager_mod, only: register_diag_field, register_static_field, send_data
use fms_mod, only: write_version_number, error_mesg, FATAL, NOTE
use fms_mod, only: open_namelist_file, check_nml_error, close_file, stdout, stdlog
use mpp_domains_mod, only: mpp_update_domains, CGRID_NE
use mpp_domains_mod, only: mpp_global_sum, BITWISE_EXACT_SUM, NON_BITWISE_EXACT_SUM
use mpp_domains_mod, only: mpp_define_domains, mpp_update_domains
use mpp_domains_mod, only: cyclic_global_domain, global_data_domain
use mpp_mod, only: mpp_error
use ocean_density_mod, only: density
use ocean_domains_mod, only: get_local_indices
use ocean_parameters_mod,only: missing_value, rho0r
use ocean_parameters_mod,only: TERRAIN_FOLLOWING
use ocean_types_mod, only: ocean_domain_type, ocean_grid_type, ocean_time_type, ocean_options_type
use ocean_types_mod, only: ocean_prog_tracer_type, ocean_density_type, ocean_thickness_type
use ocean_util_mod, only: write_timestamp
use ocean_workspace_mod, only: wrk1, wrk2, wrk3, wrk4
implicit none
private
public ocean_overflow_init
public overflow
type(ocean_domain_type), pointer :: Dom => NULL()
type(ocean_grid_type), pointer :: Grd => NULL()
#include
! for the algorithm
real :: overflow_factor ! grav*overflow_delta/(rho0*overflow_mu) (m^4/kg/sec)
integer :: ip(4),jq(4) ! to label four surrounding cells
integer :: ijsc(4),ijec(4) ! for shifting do-loop indices to minimize calls to mpp_update_domains
real, dimension(:,:), allocatable :: slope_x ! topog slope (dimensionless) in the i-direction
real, dimension(:,:), allocatable :: slope_y ! topog slope (dimensionless) in the j-direction
real, dimension(:,:,:), allocatable :: topog_slope ! topog slope (dimensionless) for 4-directions
real, dimension(:,:,:), allocatable :: topog_step ! where downslope flow is topgraphically possible
real, dimension(:,:,:), allocatable :: flux_int_z ! for diagnostics
real, dimension(:,:,:), allocatable :: source_overflow ! thickness weighted tendency from overflow
real, dimension(:,:,:), allocatable :: overflow_flux ! tracer flux associated with overflow
real, dimension(:,:), allocatable :: overflow_xflux ! mass flux in i-direction
real, dimension(:,:), allocatable :: overflow_yflux ! mass flux in j-direction
! for diagnostic manager
logical :: used
integer :: id_over_slope_x=-1
integer :: id_over_slope_y=-1
integer :: id_topog_step_1=-1
integer :: id_topog_step_2=-1
integer :: id_topog_step_3=-1
integer :: id_topog_step_4=-1
integer :: id_overflow_xflux=-1
integer :: id_overflow_yflux=-1
integer, dimension(:), allocatable :: id_overflow
integer, dimension(:), allocatable :: id_overflow_xflux_int_z
integer, dimension(:), allocatable :: id_overflow_yflux_int_z
character(len=128) :: version=&
'=>Using: ocean_overflow.f90 ($Id: ocean_overflow.F90,v 16.0.54.2.44.1 2009/10/10 00:42:44 nnz Exp $)'
character (len=128) :: tagname=&
'$Name: mom4p1_pubrel_dec2009_nnz $'
! number of prognostic tracers
integer :: num_prog_tracers=0
! processor zero writes to unit 6
integer :: unit=6
! initialization flag
logical :: module_is_initialized=.false.
! flag for mpp_global_sum
integer :: global_sum_flag
! time step
real :: dtime
real :: p5dtimer
! set from nml
logical :: use_this_module = .false. ! must be set .true. in nml to enable this scheme
logical :: debug_this_module = .false. ! for debugging
logical :: do_bitwise_exact_sum = .false. ! set true to get slower sum that is same for all PEs.
logical :: no_return_flow = .false. ! set true to remove the pre-defined return flow "piping"
real :: overflow_mu = 1.e-4 ! frictional dissipation rate (sec^-1) at bottom
real :: overflow_delta = 0.3333 ! fraction of a grid cell participating in overflow
real :: overflow_umax = 0.01 ! maximum downslope speed (m/s)
namelist /ocean_overflow_nml/ use_this_module, debug_this_module, overflow_mu, &
overflow_delta, overflow_umax, do_bitwise_exact_sum, &
no_return_flow
contains
!#######################################################################
!
!
!
! Initial set up for mixing of tracers into the abyss next to topography.
!
!
subroutine ocean_overflow_init(Grid, Domain, Time, T_prog, Ocean_options, &
vert_coordinate_type, dtim, debug)
type(ocean_grid_type), intent(in), target :: Grid
type(ocean_domain_type), intent(in), target :: Domain
type(ocean_time_type), intent(in), target :: Time
type(ocean_prog_tracer_type), intent(inout) :: T_prog(:)
type(ocean_options_type), intent(inout) :: Ocean_options
integer, intent(in) :: vert_coordinate_type
real, intent(in) :: dtim
logical, intent(in), optional :: debug
integer :: io_status, ioun, ierr
integer :: i,j,m,n,kbot
integer :: stdoutunit,stdlogunit
stdoutunit=stdout();stdlogunit=stdlog()
if ( module_is_initialized ) then
call mpp_error(FATAL, &
'==>Error from ocean_overflow_mod (ocean_overflow_init): module already initialized')
endif
module_is_initialized = .TRUE.
call write_version_number( version, tagname )
#ifndef MOM4_STATIC_ARRAYS
call get_local_indices(Domain,isd,ied,jsd,jed,isc,iec,jsc,jec)
nk = Grid%nk
#endif
Dom => Domain
Grd => Grid
num_prog_tracers = size(T_prog(:))
dtime = dtim
p5dtimer = 0.5/dtime
! provide for namelist over-ride of default values
ioun = open_namelist_file()
read (ioun,ocean_overflow_nml,IOSTAT=io_status)
write (stdlogunit,ocean_overflow_nml)
write (stdoutunit,'(/)')
write (stdoutunit,ocean_overflow_nml)
ierr = check_nml_error(io_status,'ocean_overflow_nml')
call close_file (ioun)
if(do_bitwise_exact_sum) then
global_sum_flag = BITWISE_EXACT_SUM
else
global_sum_flag = NON_BITWISE_EXACT_SUM
endif
if (PRESENT(debug) .and. .not. debug_this_module) then
debug_this_module = debug
endif
if(debug_this_module) then
write(stdoutunit,'(a)') '==>Note: running ocean_overflow_mod with debug_this_module=.true.'
endif
if(.not. use_this_module) then
call mpp_error(NOTE,&
'==>From ocean_overflow_mod: NOT using Campin and Goosse overflow scheme.')
Ocean_options%overflow = 'Did NOT use Campin and Goosse overflow scheme.'
return
else
if(vert_coordinate_type == TERRAIN_FOLLOWING) then
call mpp_error(FATAL, &
'==>ocean_overflow_mod: this module is NOT for use with TERRAIN_FOLLOWING vert coodinates.')
endif
Ocean_options%overflow = 'Used the Campin and Goosse overflow scheme.'
if(no_return_flow) then
call mpp_error(NOTE,&
'==>From ocean_overflow_mod: USING modified Campin and Goosse overflow scheme with no specified return flow.')
else
call mpp_error(NOTE,&
'==>From ocean_overflow_mod: USING original Campin and Goosse overflow scheme with specified return flow.')
endif
endif
if(debug_this_module) then
call mpp_error(NOTE,'==>From ocean_overflow_mod: USING debug_this_module')
endif
! for holding the tracer tendency from the overflow scheme
allocate (source_overflow(isd:ied,jsd:jed,nk))
source_overflow(:,:,:) = 0.0
! compute a common factor that is time independent
overflow_factor = grav*overflow_delta*rho0r/(epsln+overflow_mu)
! compute topographic slope arrays for the i-slope and j-slope
! slopes are centered on the i-face and j-face of tracer cells
allocate (slope_x(isd:ied,jsd:jed))
allocate (slope_y(isd:ied,jsd:jed))
slope_x = 0.0
slope_y = 0.0
do j=jsc,jec
do i=isc,iec
slope_x(i,j) = (Grd%ht(i+1,j)-Grd%ht(i,j))*Grd%dxter(i,j)
slope_y(i,j) = (Grd%ht(i,j+1)-Grd%ht(i,j))*Grd%dytnr(i,j)
slope_x(i,j) = abs(slope_x(i,j))
slope_y(i,j) = abs(slope_y(i,j))
enddo
enddo
call mpp_update_domains(slope_x(:,:),Dom%domain2d)
call mpp_update_domains(slope_y(:,:),Dom%domain2d)
! topographic slope for the four surrounding directions
allocate (topog_slope(isd:ied,jsd:jed,4))
topog_slope(:,:,:) = 0.0
do j=jsc,jec
do i=isc,iec
m=1 ; topog_slope(i,j,m) = slope_x(i,j)
m=2 ; topog_slope(i,j,m) = slope_y(i,j)
m=3 ; topog_slope(i,j,m) = slope_x(i-1,j)
m=4 ; topog_slope(i,j,m) = slope_y(i,j-1)
enddo
enddo
! compute directions from an (i,j) point where topography deepens.
! these directions may potentially have downslope flow.
! insist that downslope flow occurs only when there are more kmt cells
! in the adjacent column.
! also insist that downslope flow does not involve k=1 cells.
allocate (topog_step(isd:ied,jsd:jed,4))
topog_step(:,:,:) = 0.0
do j=jsc,jec
do i=isc,iec
kbot = Grd%kmt(i,j)
if(kbot > 1) then
if(Grd%kmt(i+1,j) > kbot) topog_step(i,j,1)=1.0
if(Grd%kmt(i,j+1) > kbot) topog_step(i,j,2)=1.0
if(Grd%kmt(i-1,j) > kbot) topog_step(i,j,3)=1.0
if(Grd%kmt(i,j-1) > kbot) topog_step(i,j,4)=1.0
endif
enddo
enddo
! Block out the bipolar fold in order to ensure tracer conservation.
! The reason we do so is related to how the algorithm reaches between
! two adjacent columns of tracer points. When the column straddles
! the bipolar fold, the code logic is not general and so it actually
! attempts to reach to a non-adjacent column. Shy of generalizing
! the logic, we simply do not consider overflow for points along fold.
if(jec+Dom%joff==Dom%jeg) then
topog_step(:,jec,:) = 0.0
endif
! labels for the four tracer cells surrounding a
! central tracer cell (moving counter-clockwise)
m=1 ; ip(m)=1 ; jq(m)=0 ; ijsc(m) = 1 ; ijec(m) = 0
m=2 ; ip(m)=0 ; jq(m)=1 ; ijsc(m) = 1 ; ijec(m) = 0
m=3 ; ip(m)=-1 ; jq(m)=0 ; ijsc(m) = 0 ; ijec(m) = 1
m=4 ; ip(m)=0 ; jq(m)=-1 ; ijsc(m) = 0 ; ijec(m) = 1
! for overflow flux
allocate (overflow_flux(isd:ied,jsd:jed,4))
overflow_flux(:,:,:) = 0.0
! for diagnosing vertically integrated tracer flux
allocate (flux_int_z(isd:ied,jsd:jed,4))
flux_int_z = 0.0
! for diagnostics with the traditional overflow scheme
allocate (overflow_xflux(isd:ied,jsd:jed))
allocate (overflow_yflux(isd:ied,jsd:jed))
overflow_xflux(:,:) = 0.0
overflow_yflux(:,:) = 0.0
! register/send diagnostics
id_over_slope_x = register_static_field ('ocean_model', 'over_slope_x', Grd%tracer_axes_flux_x(1:2), &
'|d(ht)/dx| on T-cell face', 'm/m', missing_value=missing_value, range=(/-1.e9,1.e9/))
if (id_over_slope_x > 0) used = send_data (id_over_slope_x, slope_x(isc:iec,jsc:jec), &
Time%model_time, rmask=Grd%tmask(isc:iec,jsc:jec,1))
id_over_slope_y = register_static_field ('ocean_model', 'over_slope_y', Grd%tracer_axes_flux_y(1:2), &
'|d(ht)/dy| on T-cell face', 'm/m', missing_value=missing_value, range=(/-1.e9,1.e9/))
if (id_over_slope_y > 0) used = send_data (id_over_slope_y, slope_y(isc:iec,jsc:jec), &
Time%model_time, rmask=Grd%tmask(isc:iec,jsc:jec,1))
id_topog_step_1 = register_static_field ('ocean_model', 'topog_step_1', Grd%tracer_axes(1:2), &
'topog_step_1', 'dimensionless', missing_value=missing_value, range=(/-1.0,1.0/))
if (id_topog_step_1 > 0) used = send_data (id_topog_step_1, topog_step(isc:iec,jsc:jec,1), &
Time%model_time, rmask=Grd%tmask(isc:iec,jsc:jec,1))
id_topog_step_2 = register_static_field ('ocean_model', 'topog_step_2', Grd%tracer_axes(1:2), &
'topog_step_2', 'dimensionless', missing_value=missing_value, range=(/-1.0,1.0/))
if (id_topog_step_2 > 0) used = send_data (id_topog_step_2, topog_step(isc:iec,jsc:jec,2), &
Time%model_time, rmask=Grd%tmask(isc:iec,jsc:jec,1))
id_topog_step_3 = register_static_field ('ocean_model', 'topog_step_3', Grd%tracer_axes(1:2), &
'topog_step_3', 'dimensionless', missing_value=missing_value, range=(/-1.0,1.0/))
if (id_topog_step_3 > 0) used = send_data (id_topog_step_3, topog_step(isc:iec,jsc:jec,3), &
Time%model_time, rmask=Grd%tmask(isc:iec,jsc:jec,1))
id_topog_step_4 = register_static_field ('ocean_model', 'topog_step_4', Grd%tracer_axes(1:2), &
'topog_step_4', 'dimensionless', missing_value=missing_value, range=(/-1.0,1.0/))
if (id_topog_step_4 > 0) used = send_data (id_topog_step_4, topog_step(isc:iec,jsc:jec,4), &
Time%model_time, rmask=Grd%tmask(isc:iec,jsc:jec,1))
id_overflow_xflux = register_diag_field ('ocean_model', 'overflow_xflux', Grd%tracer_axes_flux_x(1:2), &
Time%model_time, 'off-shelf i-transport from overflow', &
'kg/s', missing_value=missing_value, range=(/-1.e14,1.e14/))
id_overflow_yflux = register_diag_field ('ocean_model', 'overflow_yflux', Grd%tracer_axes_flux_y(1:2), &
Time%model_time, 'off-shelf j-transport from overflow', &
'kg/s', missing_value=missing_value, range=(/-1.e9,1.e9/))
allocate (id_overflow(num_prog_tracers))
allocate (id_overflow_xflux_int_z(num_prog_tracers))
allocate (id_overflow_yflux_int_z(num_prog_tracers))
id_overflow = -1
id_overflow_xflux_int_z=-1
id_overflow_yflux_int_z=-1
do n=1,num_prog_tracers
if(T_prog(n)%name == 'temp') then
id_overflow(n) = register_diag_field ('ocean_model', &
'overflow_'//trim(T_prog(n)%name), &
Grd%tracer_axes(1:3), Time%model_time, &
'cp*overflow*rho*dzt*temp', &
'Watt/m^2', missing_value=missing_value, range=(/-1.e9,1.e9/))
id_overflow_xflux_int_z(n) = register_diag_field ('ocean_model', &
trim(T_prog(n)%name)//'_xflux_overflow_int_z', &
Grd%tracer_axes_flux_x(1:2), Time%model_time, &
'vert-integ cp*overflow_xflux*rho*dzt*dyt*temp', &
'Watt', missing_value=missing_value, range=(/-1.e9,1.e9/))
id_overflow_yflux_int_z(n) = register_diag_field ('ocean_model', &
trim(T_prog(n)%name)//'_yflux_overflow_int_z', &
Grd%tracer_axes_flux_y(1:2), Time%model_time, &
'vert-integ cp*overflow_yflux*rho*dzt*dxt*temp', &
'Watt', missing_value=missing_value, range=(/-1.e9,1.e9/))
else
id_overflow(n) = register_diag_field ('ocean_model', &
'overflow_'//trim(T_prog(n)%name), &
Grd%tracer_axes(1:3), Time%model_time, &
'overflow*rho*dzt*tracer for '//trim(T_prog(n)%name),&
trim(T_prog(n)%flux_units), missing_value=missing_value, range=(/-1.e9,1.e9/))
id_overflow_xflux_int_z(n) = register_diag_field ('ocean_model', &
trim(T_prog(n)%name)//'_xflux_overflow_int_z', &
Grd%tracer_axes_flux_x(1:2), Time%model_time, &
'vert-integ overflow_xflux*dyt*rho*dzt*tracer for', &
'kg/sec', missing_value=missing_value, range=(/-1.e9,1.e9/))
id_overflow_yflux_int_z(n) = register_diag_field ('ocean_model', &
trim(T_prog(n)%name)//'_yflux_overflow_int_z', &
Grd%tracer_axes_flux_y(1:2), Time%model_time, &
'vert-integ overflow_yflux*dxt*rho*dzt*tracer for', &
'kg/sec', missing_value=missing_value, range=(/-1.e9,1.e9/))
endif
enddo
if (debug_this_module) then
write(stdoutunit,*) ' '
write(stdoutunit,*) '==Global sums from ocean_overflow_mod== '
call write_timestamp(Time%model_time)
write(stdoutunit,'(a,es24.17)') &
'slope_x = ',mpp_global_sum(Dom%domain2d,slope_x(:,:), global_sum_flag)
write(stdoutunit,'(a,es24.17)') &
'slope_y = ',mpp_global_sum(Dom%domain2d,slope_y(:,:), global_sum_flag)
write(stdoutunit,'(a,es24.17)') &
'topog_slope(1) = ',mpp_global_sum(Dom%domain2d,topog_slope(:,:,1), global_sum_flag)
write(stdoutunit,'(a,es24.17)') &
'topog_slope(2) = ',mpp_global_sum(Dom%domain2d,topog_slope(:,:,2), global_sum_flag)
write(stdoutunit,'(a,es24.17)') &
'topog_slope(3) = ',mpp_global_sum(Dom%domain2d,topog_slope(:,:,3), global_sum_flag)
write(stdoutunit,'(a,es24.17)') &
'topog_slope(4) = ',mpp_global_sum(Dom%domain2d,topog_slope(:,:,4), global_sum_flag)
write(stdoutunit,'(a,es24.17)') &
'topog_step(1) = ',mpp_global_sum(Dom%domain2d,topog_step(:,:,1), global_sum_flag)
write(stdoutunit,'(a,es24.17)') &
'topog_step(2) = ',mpp_global_sum(Dom%domain2d,topog_step(:,:,2), global_sum_flag)
write(stdoutunit,'(a,es24.17)') &
'topog_step(3) = ',mpp_global_sum(Dom%domain2d,topog_step(:,:,3), global_sum_flag)
write(stdoutunit,'(a,es24.17)') &
'topog_step(4) = ',mpp_global_sum(Dom%domain2d,topog_step(:,:,4), global_sum_flag)
endif
end subroutine ocean_overflow_init
! NAME="ocean_overflow_init"
!#######################################################################
!
!
!
! Compute thickness and density weighted tracer source [tracer*rho*m/s]
! due to upstream tracer advection in regions where density-driven
! overflows are favorable.
!
! The MOM4 implementation of the Campin and Goosse (1999)
! algorithm is detailed in the MOM4 Technical Guide.
!
!
!
subroutine overflow (Time, Thickness, T_prog, Dens, index_temp, index_salt)
type(ocean_time_type), intent(in) :: Time
type(ocean_thickness_type), intent(inout) :: Thickness
type(ocean_prog_tracer_type), intent(inout) :: T_prog(:)
type(ocean_density_type), intent(in) :: Dens
integer, intent(in) :: index_temp
integer, intent(in) :: index_salt
integer, dimension(isd:ied,jsd:jed,4) :: kup
integer, dimension(isd:ied,jsd:jed,4) :: kdw
real, dimension(0:nk) :: source_check
real, dimension(0:nk) :: flux
real, dimension(nk) :: source_column
real, dimension(isd:ied,jsd:jed) :: tmp
integer :: tau, taum1
integer :: i, j, k, m, n
real :: temp_so, salt_so, press, density_check
real :: overflow_thickness, overflow_speed
real :: max_overflow_flux
integer :: stdoutunit,stdlogunit
stdoutunit=stdout();stdlogunit=stdlog()
if(.not. use_this_module) return
if(.not. module_is_initialized ) then
call mpp_error(FATAL, &
'==>Error from ocean_overflow_mod (overflow): module must be initialized')
endif
tau = Time%tau
taum1 = Time%taum1
! compute grid details for cells participating in downslope flow
! note: "so" = "shallow ocean" cell
! note: "do" = cells within the "deep ocean" column
kup(:,:,:) = 0
kdw(:,:,:) = 0
overflow_flux(:,:,:) = 0.0
overflow_xflux(:,:) = 0.0
overflow_yflux(:,:) = 0.0
do m=1,4
do j=jsc,jec
do i=isc,iec
max_overflow_flux = Grd%dat(i,j)*p5dtimer
! check to see if downslope flow is topographically possible
if(topog_step(i,j,m) == 1.0) then
! check to see if density of so-cell > density of adjacent do-cell
k = Grd%kmt(i,j)
if(Dens%rho(i,j,k,tau) > Dens%rho(i+ip(m),j+jq(m),k,tau)) then
! k-level of shallow-ocn (so) bottom cell
kup(i,j,m) = Grd%kmt(i,j)
! speed (m/sec) of downslope flow
k=kup(i,j,m)
temp_so = T_prog(index_temp)%field(i,j,k,tau)
salt_so = T_prog(index_salt)%field(i,j,k,tau)
overflow_speed = overflow_factor*topog_slope(i,j,m) &
*(Dens%rho(i,j,k,tau)-Dens%rho(i+ip(m),j+jq(m),k,tau))
overflow_speed = min(overflow_speed,overflow_umax)
! kdw = k-level in the do-column where so-cell is neutrally buoyant or at bottom
kdw(i,j,m) = kup(i,j,m)
do k=kup(i,j,m)+1,Grd%kmt(i+ip(m),j+jq(m))
press = Dens%pressure_at_depth(i+ip(m),j+jq(m),k)
density_check = density(salt_so,temp_so,press)
if(density_check > Dens%rho(i+ip(m),j+jq(m),k,tau)) then
kdw(i,j,m)=k
else
exit
endif
enddo
! compute m^2/sec flux leaving vertical face of cell
if(m==1 .or. m==3) then
overflow_flux(i,j,m)=overflow_speed*Grd%dyt(i,j)
elseif(m==2 .or. m==4) then
overflow_flux(i,j,m)=overflow_speed*Grd%dxt(i,j)
endif
! check for too large flux. based on 1D diffusive stability criteria,
! no more than one-half the mass of a grid cell can be mixed per time
! step, which means
! overflow_flux(m^2/sec)*rho_dzt*dtime < 0.5*rho_dzt*dat,
! or equivalently overflow_flux(m^2/sec) < 0.5*dat/dtime
overflow_flux(i,j,m) = min(overflow_flux(i,j,m),max_overflow_flux)
! convert from m^2/sec to (kg/sec) using min rho_dzt
k=kup(i,j,m)
overflow_thickness = min(Thickness%rho_dzt(i,j,k,tau), &
Thickness%rho_dzt(i+ip(m),j+jq(m),k,tau))
do k=kup(i,j,m),kdw(i,j,m)
overflow_thickness = min(overflow_thickness,Thickness%rho_dzt(i+ip(m),j+jq(m),k,tau))
enddo
overflow_flux(i,j,m) = overflow_flux(i,j,m)*overflow_thickness
! for diagnostics: mass transport (kg/sec) off the shelf
if(m==1) overflow_xflux(i,j) = overflow_xflux(i,j) + overflow_flux(i,j,m)
if(m==2) overflow_yflux(i,j) = overflow_yflux(i,j) + overflow_flux(i,j,m)
if(m==3) overflow_xflux(i,j) = overflow_xflux(i,j) - overflow_flux(i,j,m)
if(m==4) overflow_yflux(i,j) = overflow_yflux(i,j) - overflow_flux(i,j,m)
endif ! if-test for density difference
endif ! if-test for topog_step(i,j,m)==1.0
enddo ! i-end
enddo ! j-end
enddo ! m-end for the four surrounding cells
call mpp_update_domains(overflow_flux(:,:,:),Dom%domain2d)
call mpp_update_domains(kup(:,:,:),Dom%domain2d)
call mpp_update_domains(kdw(:,:,:),Dom%domain2d)
if (debug_this_module) then
write(stdoutunit,*) ' '
write(stdoutunit,*) '==Global sums from ocean_overflow_mod== '
call write_timestamp(Time%model_time)
write(stdoutunit,'(a,es24.17)') 'overflow_flux(1)(kg/sec) = ',&
mpp_global_sum(Dom%domain2d,overflow_flux(:,:,1), global_sum_flag)
write(stdoutunit,'(a,es24.17)') 'overflow_flux(2)(kg/sec) = ',&
mpp_global_sum(Dom%domain2d,overflow_flux(:,:,2), global_sum_flag)
write(stdoutunit,'(a,es24.17)') 'overflow_flux(3)(kg/sec) = ',&
mpp_global_sum(Dom%domain2d,overflow_flux(:,:,3), global_sum_flag)
write(stdoutunit,'(a,es24.17)') 'overflow_flux(4)(kg/sec) = ',&
mpp_global_sum(Dom%domain2d,overflow_flux(:,:,4), global_sum_flag)
write(stdoutunit,'(a,i22)') 'kup(1) = ',&
mpp_global_sum(Dom%domain2d,kup(:,:,1), global_sum_flag)
write(stdoutunit,'(a,i22)') 'kup(2) = ',&
mpp_global_sum(Dom%domain2d,kup(:,:,2), global_sum_flag)
write(stdoutunit,'(a,i22)') 'kup(3) = ',&
mpp_global_sum(Dom%domain2d,kup(:,:,3), global_sum_flag)
write(stdoutunit,'(a,i22)') 'kup(4) = ',&
mpp_global_sum(Dom%domain2d,kup(:,:,4), global_sum_flag)
write(stdoutunit,'(a,i22)') 'kdw(1) = ',&
mpp_global_sum(Dom%domain2d,kdw(:,:,1), global_sum_flag)
write(stdoutunit,'(a,i22)') 'kdw(2) = ',&
mpp_global_sum(Dom%domain2d,kdw(:,:,2), global_sum_flag)
write(stdoutunit,'(a,i22)') 'kdw(3) = ',&
mpp_global_sum(Dom%domain2d,kdw(:,:,3), global_sum_flag)
write(stdoutunit,'(a,i22)') 'kdw(4) = ',&
mpp_global_sum(Dom%domain2d,kdw(:,:,4), global_sum_flag)
endif
! compute fluxes and the source for those
! cells participating in downslope transport
! do the mass first
if (no_return_flow) then
source_overflow(:,:,:) = 0.0
flux_int_z(:,:,:) = 0.0
wrk1(:,:,:)=0.0 ; wrk2(:,:,:)=0.0 ; wrk3(:,:,:)=0.0 ; wrk4(:,:,:)=0.0
flux(:) = 0.0
! extended do-loop limits perform extra computations, but
! save time by reducing need to call to mpp_update_domains.
do m=1,4
do j=jsc-ijsc(m),jec+ijec(m)
do i=isc-ijsc(m),iec+ijec(m)
! see if (i,j) is a so-cell participating in downslope flow in the m-direction
if(kup(i,j,m) > 0) then
! initialize upstream tracer flux leaving tracer cells
flux(0) = 0.0
! initialize thickness*density weighted tendency in column
source_column(:) = 0.0
! flux horizontally leaving so-cell at k=kup and entering do-cell at k=kdw
k=kup(i,j,m)
flux(0) = overflow_flux(i,j,m)
! source for so-cell at k=kup [(kg/m^3)*(m/s)]
source_overflow(i,j,k) = source_overflow(i,j,k) - Grd%datr(i,j)*flux(0)
! source for do-cell at k=kdw [(kg/m^3)*(m/s)]
k = kdw(i,j,m)
source_column(k) = Grd%datr(i+ip(m),j+jq(m)) * flux(0)
if(m==1) wrk1(i,j,:) = source_column(:)
if(m==2) wrk2(i,j,:) = source_column(:)
if(m==3) wrk3(i,j,:) = source_column(:)
if(m==4) wrk4(i,j,:) = source_column(:)
endif ! kup(i,j,m) > 0
enddo ! i-end
enddo ! j-end
enddo ! m-end for the four directions
! each cell can have a source five different ways:
! 1: when cell is the so-cell
! 2-5: when cell is one of the do-cells for adjacent so-cells.
do k=1,nk
do j=jsc,jec
do i=isc,iec
source_overflow(i,j,k) = source_overflow(i,j,k) &
+ wrk1(i-1,j,k) &
+ wrk2(i,j-1,k) &
+ wrk3(i+1,j,k) &
+ wrk4(i,j+1,k)
if (source_overflow(i,j,k) .ne. 0.0) then
Thickness%mass_source(i,j,k) = Thickness%mass_source(i,j,k) + source_overflow(i,j,k)
endif
enddo
enddo
enddo
call mpp_update_domains(Thickness%mass_source(:,:,:),Dom%domain2d)
endif ! no_return_flow?
! now do the tracer
! tracer source = convergence of upstream advective fluxes
do n=1,num_prog_tracers
source_overflow(:,:,:) = 0.0
flux_int_z(:,:,:) = 0.0
wrk1=0.0 ; wrk2=0.0 ; wrk3=0.0 ; wrk4=0.0
! extended do-loop limits perform extra computations, but
! save time by reducing need to call to mpp_update_domains.
do m=1,4
do j=jsc-ijsc(m),jec+ijec(m)
do i=isc-ijsc(m),iec+ijec(m)
! see if (i,j) is a so-cell participating in downslope flow in the m-direction
if(kup(i,j,m) > 0) then
! initialize upstream tracer flux leaving tracer cells
flux(:) = 0.0
! initialize thickness*density weighted tendency in column
source_column(:) = 0.0
! flux horizontally leaving so-cell at k=kup and entering do-cell at k=kdw
k=kup(i,j,m)
flux(0) = overflow_flux(i,j,m)*T_prog(n)%field(i,j,k,taum1)
if (.not. no_return_flow) then
! flux leaving do-cells
do k=kup(i,j,m),kdw(i,j,m)
flux(k) = overflow_flux(i,j,m)*T_prog(n)%field(i+ip(m),j+jq(m),k,taum1)
enddo
! source for so-cell at k=kup [tracer*(kg/m^3)*(m/s)]
k = kup(i,j,m)
source_overflow(i,j,k) = source_overflow(i,j,k) + Grd%datr(i,j)*flux(k)
! source for do-cell at k=kdw [tracer*(kg/m^3)*(m/s)]
k = kdw(i,j,m)
source_column(k) = - Grd%datr(i+ip(m),j+jq(m))*flux(k)
! source for do-cell with kup <= k <= kdw-1 [tracer*(kg/m^3)*(m/s)]
if(kdw(i,j,m) > kup(i,j,m)) then
do k = kup(i,j,m),kdw(i,j,m)-1
source_column(k) = Grd%datr(i+ip(m),j+jq(m))*(flux(k+1)-flux(k))
enddo
endif
endif !.not. no_return_flow
! for diagnosing vertically integrated horizontal flux
flux_int_z(i,j,m) = flux_int_z(i,j,m) + flux(0)-flux(kup(i,j,m))
! source for so-cell at k=kup [tracer*(kg/m^3)*(m/s)]
k = kup(i,j,m)
source_overflow(i,j,k) = source_overflow(i,j,k) - Grd%datr(i,j)*flux(0)
! source for do-cell at k=kdw [tracer*(kg/m^3)*(m/s)]
k = kdw(i,j,m)
source_column(k) = source_column(k) + Grd%datr(i+ip(m),j+jq(m))*flux(0)
if(m==1) wrk1(i,j,:) = source_column(:)
if(m==2) wrk2(i,j,:) = source_column(:)
if(m==3) wrk3(i,j,:) = source_column(:)
if(m==4) wrk4(i,j,:) = source_column(:)
endif ! kup(i,j,m) > 0
enddo ! i-end
enddo ! j-end
enddo ! m-end for the four directions
! each cell can have a source five different ways:
! 1: when cell is the so-cell
! 2-5: when cell is one of the do-cells for adjacent so-cells.
do k=1,nk
do j=jsc,jec
do i=isc,iec
source_overflow(i,j,k) = source_overflow(i,j,k) &
+ wrk1(i-1,j,k) &
+ wrk2(i,j-1,k) &
+ wrk3(i+1,j,k) &
+ wrk4(i,j+1,k)
if (source_overflow(i,j,k) .ne. 0.0) then
T_prog(n)%th_tendency(i,j,k) = T_prog(n)%th_tendency(i,j,k) + source_overflow(i,j,k)
endif
enddo
enddo
enddo
if (debug_this_module) then
source_check(:) = 0.0
do k=1,nk
do j=jsc,jec
do i=isc,iec
tmp(i,j) = T_prog(n)%conversion*dtime*Grd%dat(i,j)*source_overflow(i,j,k)
enddo
enddo
source_check(k) = mpp_global_sum(Dom%domain2d,tmp(:,:), global_sum_flag)
enddo
do k=1,nk
source_check(0) = source_check(0) + source_check(k)
enddo
if(T_prog(n)%name == 'temp' ) then
write(stdoutunit,'(a,i3,a,es24.17)') &
'For tracer(',n,'), (temp ) total overflow source is (J) ', source_check(0)
elseif(T_prog(n)%name == 'salt' ) then
write(stdoutunit,'(a,i3,a,es24.17)') &
'For tracer(',n,'), (salt ) total overflow source is (kg)', source_check(0)
else
write(stdoutunit,'(a,i3,a,es24.17)') &
'For tracer(',n,'), (passive) total overflow source is (kg)', source_check(0)
endif
endif
if(id_overflow(n) > 0) then
used = send_data (id_overflow(n), T_prog(n)%conversion*source_overflow(:,:,:), &
Time%model_time, rmask=Grd%tmask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
if(id_overflow_xflux_int_z(n) > 0) then
used = send_data (id_overflow_xflux_int_z(n), &
T_prog(n)%conversion*(flux_int_z(:,:,1)-flux_int_z(:,:,3)), &
Time%model_time, rmask=Grd%tmask(:,:,1), &
is_in=isc, js_in=jsc, ie_in=iec, je_in=jec)
endif
if(id_overflow_yflux_int_z(n) > 0) then
used = send_data (id_overflow_yflux_int_z(n), &
T_prog(n)%conversion*(flux_int_z(:,:,2)-flux_int_z(:,:,4)), &
Time%model_time, rmask=Grd%tmask(:,:,1), &
is_in=isc, js_in=jsc, ie_in=iec, je_in=jec)
endif
enddo ! n-end for num_prog_tracers
! tracer independent mass transports
if(id_overflow_xflux > 0) then
used = send_data (id_overflow_xflux, overflow_xflux(:,:), &
Time%model_time, rmask=Grd%tmask(:,:,1), &
is_in=isc, js_in=jsc, ie_in=iec, je_in=jec)
endif
if(id_overflow_yflux > 0) then
used = send_data (id_overflow_yflux, overflow_yflux(:,:), &
Time%model_time, rmask=Grd%tmask(:,:,1), &
is_in=isc, js_in=jsc, ie_in=iec, je_in=jec)
endif
end subroutine overflow
! NAME="overflow"
end module ocean_overflow_mod