!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! !!
!! 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_pressure_mod
!
!
! S.M. Griffies
!
!
! R.C. Pacanowski
!
!
!
! A. Rosati
!
!
!
! Compute the hydrostatic pressure and forces from pressure.
!
!
!
! This module computes hydrostatic pressure and the pressure force
! acting at a velocity point (traditional finite difference approach).
! This force is used for the linear momentum equation.
!
! This module takes account of the vertical coordinate,
! which determines details of the calculation.
!
!
!
!
!
! "Elements of mom4p1"
! S.M. Griffies, (2007)
!
!
!
!
!
!
! For debugging.
!
!
!
! For debugging it is often useful to zero the contribution to the
! pressure gradient that arises from the "correction" term.
! Implemented only for depth based vertical coordinate models.
!
!
! For debugging it is often useful to zero the contribution to the
! pressure gradient that arises from the along k-level gradient.
! Implemented only for depth based vertical coordinate models.
!
!
! For debugging it is often useful to zero the pressure force
! to zero.
!
!
! For debugging zstar, we drop any eta/H contribution to
! the hydrostatic pressure. This is wrong physically, but
! useful for certain tests.
!
!
!
use constants_mod, only: grav, c2dbars, epsln
use diag_manager_mod, only: register_diag_field, send_data
use fms_mod, only: open_namelist_file, check_nml_error, close_file, write_version_number
use mpp_io_mod, only: mpp_open, mpp_close, MPP_RDONLY, MPP_ASCII
use mpp_mod, only: mpp_error, FATAL, stdout, stdlog, mpp_chksum
use ocean_domains_mod, only: get_local_indices
use ocean_operators_mod, only: FAY, FAX, FDX_NT, FDY_ET
use ocean_parameters_mod, only: GEOPOTENTIAL, ZSTAR, ZSIGMA
use ocean_parameters_mod, only: PRESSURE, PSTAR, PSIGMA
use ocean_parameters_mod, only: DEPTH_BASED, PRESSURE_BASED
use ocean_parameters_mod, only: ENERGETIC, FINITEVOLUME
use ocean_parameters_mod, only: missing_value, rho0, rho0r
use ocean_types_mod, only: ocean_domain_type, ocean_grid_type
use ocean_types_mod, only: ocean_time_type, ocean_velocity_type
use ocean_types_mod, only: ocean_thickness_type, ocean_density_type
use ocean_util_mod, only: write_timestamp
use ocean_workspace_mod, only: wrk1, wrk2, wrk1_zw, wrk2_zw, wrk1_v, wrk2_v, wrk1_2d
use ocean_obc_mod, only: store_ocean_obc_pressure_grad
implicit none
private
public ocean_pressure_init
public pressure_in_dbars
public pressure_force
public hydrostatic_pressure
public geopotential_anomaly
private pressure_gradient_force_depth
private pressure_gradient_force_press
#include
type(ocean_domain_type), pointer :: Dom =>NULL()
type(ocean_grid_type), pointer :: Grd =>NULL()
character(len=128) :: version = &
'$Id: ocean_pressure.F90,v 16.0.108.1 2009/10/10 00:41:59 nnz Exp $'
character (len=128) :: tagname = &
'$Name: mom4p1_pubrel_dec2009_nnz $'
! for vertical coordinate
integer :: vert_coordinate
integer :: vert_coordinate_class
! useful constants
real :: grav_rho0r
real :: grav_rho0
real :: p5grav
real :: p5gravr
real :: p5grav_rho0r
real :: dbars2pa
! for computing geopotential at T-cell bottom from depth_zwt
real :: geopotential_switch=0.0
! for diagnostics
integer :: id_geopotential =-1
integer :: id_anomgeopot =-1
integer :: id_anomgeopot_zwt =-1
integer :: id_anompress =-1
integer :: id_anompress_zwt =-1
integer :: id_press_force(2) =-1
integer :: id_pgrad_klev(2) =-1
integer :: id_rhoprime_geograd_klev(2) =-1
integer :: id_rhoprime_pgrad_klev(2) =-1
integer :: id_rho_geogradprime_klev(2) =-1
logical :: used
logical :: debug_this_module =.false.
logical :: zero_pressure_force =.false.
logical :: zero_correction_term_grad =.false.
logical :: zero_diagonal_press_grad =.false.
logical :: module_is_initialized =.false.
logical :: have_obc =.false.
logical :: zero_eta_over_h_zstar_pressure = .false.
namelist /ocean_pressure_nml/ debug_this_module, zero_pressure_force, &
zero_correction_term_grad, zero_diagonal_press_grad, &
zero_eta_over_h_zstar_pressure
contains
!#######################################################################
!
!
!
! Initialize the pressure module
!
!
subroutine ocean_pressure_init(Grid, Domain, Time, ver_coordinate, &
ver_coordinate_class, obc, debug)
type(ocean_grid_type), target, intent(in) :: Grid
type(ocean_domain_type), target, intent(in) :: Domain
type(ocean_time_type), intent(in) :: Time
integer, intent(in) :: ver_coordinate
integer, intent(in) :: ver_coordinate_class
logical, intent(in) :: obc
logical, optional, intent(in) :: debug
integer :: ioun, io_status, ierr
integer :: stdoutunit,stdlogunit
stdoutunit=stdout();stdlogunit=stdlog()
if ( module_is_initialized ) then
call mpp_error( FATAL, &
'==>Error: ocean_pressure_mod (ocean_pressure_init): module already initialized')
endif
module_is_initialized = .TRUE.
call write_version_number( version, tagname )
have_obc = obc
vert_coordinate = ver_coordinate
vert_coordinate_class = ver_coordinate_class
grav_rho0 = grav*rho0
grav_rho0r = grav*rho0r
p5grav = 0.5*grav
p5gravr = 0.5/grav
p5grav_rho0r = 0.5*grav*rho0r
dbars2pa = 1.0/c2dbars
ioun = open_namelist_file()
read (ioun, ocean_pressure_nml,iostat=io_status)
write (stdoutunit,'(/)')
write (stdoutunit, ocean_pressure_nml)
write (stdlogunit, ocean_pressure_nml)
ierr = check_nml_error(io_status, 'ocean_pressure_nml')
call close_file(ioun)
#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
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_pressure_mod with debug_this_module=.true.'
endif
if(zero_pressure_force) then
write(stdoutunit,*) &
'==>Warning: Running mom4 with zero horizontal pressure force. Unrealistic simulation.'
endif
if(vert_coordinate==GEOPOTENTIAL) then
geopotential_switch=0.0
else
geopotential_switch=1.0
endif
write(stdoutunit,*) &
'==>NOTE: Running mom4p1 with finite difference formulation of pressure force.'
if(zero_correction_term_grad) then
write(stdoutunit,*) &
'==>Warning: Running mom4p1 with zero_correction_term_grad=.true. Unrealistic simulation.'
endif
if(zero_diagonal_press_grad) then
write(stdoutunit,*) &
'==>Warning: Running mom4p1 with zero_diagonal_press_grad=.true. Unrealistic simulation.'
endif
! register fields
id_geopotential = register_diag_field ('ocean_model', 'geopotential', Grd%tracer_axes(1:3),&
Time%model_time, 'geopotential at T-point', 'm^2/s^2', &
missing_value=missing_value, range=(/-1e8,1e8/))
id_anompress = register_diag_field ('ocean_model', 'anompress', Grd%tracer_axes(1:3),&
Time%model_time, 'anomalous hydrostatic pressure at T-point', 'Pa', &
missing_value=missing_value, range=(/-1e8,1e8/))
id_anompress_zwt = register_diag_field ('ocean_model', 'anompress_zwt', Grd%tracer_axes(1:3),&
Time%model_time, 'anomalous hydrostatic pressure at T-cell bottom', 'Pa', &
missing_value=missing_value, range=(/-1e8,1e8/))
id_anomgeopot = register_diag_field ('ocean_model', 'anomgeopot', Grd%tracer_axes(1:3),&
Time%model_time, 'anomalous geopotential at T-point', 'm^2/s^2', &
missing_value=missing_value, range=(/-1e8,1e8/))
id_anomgeopot_zwt = register_diag_field ('ocean_model', 'anomgeopot_zwt', Grd%tracer_axes(1:3),&
Time%model_time, 'anomalous geopotential at T-cell bottom', 'm^2/s^2', &
missing_value=missing_value, range=(/-1e8,1e8/))
id_pgrad_klev(1) = register_diag_field ('ocean_model', 'dzupgrad_x_klev', Grd%vel_axes_uv(1:3), &
Time%model_time, 'dzu*dp_dx on k-level', 'Pa', missing_value=missing_value, range=(/-1e9,1e9/))
id_pgrad_klev(2) = register_diag_field ('ocean_model', 'dzupgrad_y_klev', Grd%vel_axes_uv(1:3), &
Time%model_time, 'dzu*dp_dy on k-level', 'Pa', missing_value=missing_value, range=(/-1e9,1e9/))
id_rhoprime_geograd_klev(1) = register_diag_field ('ocean_model', 'dzurhoprime_geograd_x_klev', &
Grd%vel_axes_uv(1:3), Time%model_time, 'dzu*rhoprime*d(geopot)/dx on k-level', 'Pa', &
missing_value=missing_value, range=(/-1e9,1e9/))
id_rhoprime_geograd_klev(2) = register_diag_field ('ocean_model', 'dzurhoprime_geograd_y_klev', &
Grd%vel_axes_uv(1:3), Time%model_time, 'dzu*rhoprime*d(geopot)/dx on k-level', 'Pa', &
missing_value=missing_value, range=(/-1e9,1e9/))
id_rhoprime_pgrad_klev(1) = register_diag_field ('ocean_model', 'dzurhoprime_pgrad_x_klev', &
Grd%vel_axes_uv(1:3), Time%model_time, 'dzu*(rhoprime/rho0)*dp/dx on k-level', 'Pa', &
missing_value=missing_value, range=(/-1e9,1e9/))
id_rhoprime_pgrad_klev(2) = register_diag_field ('ocean_model', 'dzurhoprime_pgrad_y_klev', &
Grd%vel_axes_uv(1:3), Time%model_time, 'dzu*(rhoprime/rho0)*dp/dy on k-level', 'Pa', &
missing_value=missing_value, range=(/-1e9,1e9/))
id_rho_geogradprime_klev(1) = register_diag_field ('ocean_model', 'dzurho_geogradprime_x_klev',&
Grd%vel_axes_uv(1:3), Time%model_time, 'dzu*rho*d(geopot_prime)/dx on k-level', 'Pa', &
missing_value=missing_value, range=(/-1e9,1e9/))
id_rho_geogradprime_klev(2) = register_diag_field ('ocean_model', 'dzurho_geogradprime_y_klev',&
Grd%vel_axes_uv(1:3), Time%model_time, 'dzu*rho*d(geopot_prime)/dy on k-level', 'Pa/m', &
missing_value=missing_value, range=(/-1e9,1e9/))
id_press_force(1) = register_diag_field ('ocean_model', 'press_force_u', &
Grd%vel_axes_uv(1:3), Time%model_time, 'i-directed pressure force', &
'Pa', missing_value=missing_value, range=(/-1e9,1e9/))
id_press_force(2) = register_diag_field ('ocean_model', 'press_force_v', &
Grd%vel_axes_uv(1:3), Time%model_time, 'j-directed pressure force', &
'Pa', missing_value=missing_value, range=(/-1e9,1e9/))
end subroutine ocean_pressure_init
! NAME="ocean_pressure_init"
!#######################################################################
!
!
!
! Compute the horizontal force [Pa=N/m^2] from pressure.
!
! Use the traditional approach whereby the pressure force
! is computed as a finite difference gradient centred
! at the U-cell point.
!
!
!
subroutine pressure_force(Time, Thickness, Dens, Velocity, rho)
type(ocean_time_type), intent(in) :: Time
type(ocean_thickness_type), intent(in) :: Thickness
type(ocean_density_type), intent(in) :: Dens
type(ocean_velocity_type), intent(inout) :: Velocity
real, dimension(isd:,jsd:,:), intent(in) :: rho
integer :: tau
integer :: stdoutunit
stdoutunit=stdout()
tau = Time%tau
if ( .not. module_is_initialized ) then
call mpp_error(FATAL, &
'==>Error in ocean_pressure_mod (pressure_force): module must be initialized')
endif
if(vert_coordinate_class==DEPTH_BASED) then
call pressure_gradient_force_depth(Time, Thickness, Velocity, rho)
else
call pressure_gradient_force_press(Time, Thickness, Dens, Velocity, rho)
endif
! for debugging
if(zero_pressure_force) then
Velocity%press_force = 0.0
endif
! for open boundaries
if (have_obc) call store_ocean_obc_pressure_grad(Thickness, Velocity%press_force, tau)
! send some diagnostics
if(id_geopotential > 0) used = send_data( id_geopotential, -grav*Thickness%geodepth_zt(:,:,:), &
Time%model_time, rmask=Grd%tmask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
if (id_press_force(1) > 0) then
used = send_data( id_press_force(1), Velocity%press_force(:,:,:,1), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
if (id_press_force(2) > 0) then
used = send_data( id_press_force(2), Velocity%press_force(:,:,:,2), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
! more debugging
if(debug_this_module) then
write(stdoutunit,*)' '
write(stdoutunit,*) 'From ocean_pressure_mod: pressure chksums'
call write_timestamp(Time%model_time)
write(stdoutunit,*) 'rho_dzu(tau) = ', &
mpp_chksum(Thickness%rho_dzu(isc:iec,jsc:jec,:,tau)*Grd%umask(isc:iec,jsc:jec,:))
write(stdoutunit,*) 'press_force(1) = ', &
mpp_chksum(Velocity%press_force(isc:iec,jsc:jec,:,1)*Grd%umask(isc:iec,jsc:jec,:))
write(stdoutunit,*) 'press_force(2) = ', &
mpp_chksum(Velocity%press_force(isc:iec,jsc:jec,:,2)*Grd%umask(isc:iec,jsc:jec,:))
endif
end subroutine pressure_force
! NAME="pressure_force"
!#######################################################################
!
!
!
! Compute the force from pressure using a finite difference method
! to compute the thickness weighted pressure gradient at the
! velocity cell point.
!
! For depth-like vertical coordinates, we exclude surface and applied
! pressures (i.e., we are computing here the gradient of the baroclinic
! pressure). Account is taken of variable partial cell thickness.
! 1 = dp/dx; 2 = dp/dy
!
! Thickness weight since this is what we wish to use in update of
! the velocity. Resulting thickness weighted pressure gradient has
! dimensions of Pa = N/m^2 = kg/(m*s^2).
!
! Thickness%dzu should be at tau.
!
!
!
subroutine pressure_gradient_force_depth(Time, Thickness, Velocity, rho)
type(ocean_time_type), intent(in) :: Time
type(ocean_thickness_type), intent(in) :: Thickness
type(ocean_velocity_type), intent(inout) :: Velocity
real, dimension(isd:,jsd:,:), intent(in) :: rho
real, dimension(isd:ied,jsd:jed) :: diff_geo_x
real, dimension(isd:ied,jsd:jed) :: diff_geo_y
real, dimension(isd:ied,jsd:jed) :: tmp1
real, dimension(isd:ied,jsd:jed) :: tmp2
integer :: i, j, k
integer :: tau
if ( .not. module_is_initialized ) then
call mpp_error(FATAL, &
'==>Error in ocean_pressure_mod (pressure_gradient_force_depth): module must be initialized')
endif
tau = Time%tau
tmp1 = 0.0
tmp2 = 0.0
wrk1_v = 0.0
wrk2_v = 0.0
! use density anomaly to improve accuracy
do k=1,nk
do j=jsd,jed
do i=isd,ied
wrk2(i,j,k) = Grd%tmask(i,j,k)*(rho(i,j,k)-rho0)
enddo
enddo
enddo
! compute hydrostatic pressure anomaly at T-point
! ( Pa=N/m^2=kg/(m*s^2) )
wrk1(:,:,:) = hydrostatic_pressure(Thickness, wrk2(:,:,:))
if(id_anompress > 0) then
used = send_data( id_anompress, wrk1(:,:,:), &
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
diff_geo_x(:,:) = 0.0
diff_geo_y(:,:) = 0.0
do k=1,nk
do j=jsd,jed
do i=isd,iec
diff_geo_x(i,j) = -grav*(Thickness%geodepth_zt(i+1,j,k)-Thickness%geodepth_zt(i,j,k))
enddo
enddo
do j=jsd,jec
do i=isd,ied
diff_geo_y(i,j) = -grav*(Thickness%geodepth_zt(i,j+1,k)-Thickness%geodepth_zt(i,j,k))
enddo
enddo
! density anomaly times geopotential gradient on k-levels
! (dzurhoprime_geograd_x_klev,dzurhoprime_geograd_y_klev)
tmp1(:,:) = FAY(FAX(wrk2(:,:,k))*diff_geo_x(:,:))
tmp2(:,:) = FAX(FAY(wrk2(:,:,k))*diff_geo_y(:,:))
do j=jsc,jec
do i=isc,iec
wrk1_v(i,j,k,1) = tmp1(i,j)*Grd%dxur(i,j)*Thickness%dzu(i,j,k)
wrk1_v(i,j,k,2) = tmp2(i,j)*Grd%dyur(i,j)*Thickness%dzu(i,j,k)
enddo
enddo
if(zero_correction_term_grad) then
wrk1_v(:,:,:,:) = 0.0
endif
! gradient of anomalous baroclinic pressure on k-levels
! (dzupgrad_x_klev,dzupgrad_y_klev)
tmp1(:,:) = FDX_NT(FAY(wrk1(:,:,k)))
tmp2(:,:) = FDY_ET(FAX(wrk1(:,:,k)))
do j=jsc,jec
do i=isc,iec
wrk2_v(i,j,k,1) = tmp1(i,j)*Thickness%dzu(i,j,k)
wrk2_v(i,j,k,2) = tmp2(i,j)*Thickness%dzu(i,j,k)
enddo
enddo
if(zero_diagonal_press_grad) then
wrk2_v(:,:,:,:) = 0.0
endif
! thickness weighted baroclinic pressure gradient on z-levels
! (dzu_pgrad_u,dzu_pgrad_v)
do j=jsc,jec
do i=isc,iec
Velocity%press_force(i,j,k,1) = -Grd%umask(i,j,k)*( wrk1_v(i,j,k,1) + wrk2_v(i,j,k,1) )
Velocity%press_force(i,j,k,2) = -Grd%umask(i,j,k)*( wrk1_v(i,j,k,2) + wrk2_v(i,j,k,2) )
enddo
enddo
enddo ! k do-loop finish
! (dzurhoprime_geograd_x_klev,dzurhoprime_geograd_y_klev)
if (id_rhoprime_geograd_klev(1) > 0) then
used=send_data( id_rhoprime_geograd_klev(1),wrk1_v(:,:,:,1), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
if (id_rhoprime_geograd_klev(2) > 0) then
used=send_data( id_rhoprime_geograd_klev(2),wrk1_v(:,:,:,2), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
! (dzupgrad_x_klev,dzupgrad_y_klev)
if (id_pgrad_klev(1) > 0) then
used = send_data( id_pgrad_klev(1), wrk2_v(:,:,:,1), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
if (id_pgrad_klev(2) > 0) then
used = send_data( id_pgrad_klev(2), wrk2_v(:,:,:,2), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
end subroutine pressure_gradient_force_depth
! NAME="pressure_gradient_force_depth"
!#######################################################################
!
!
!
! Compute the force from pressure using a finite difference method
! to compute the thickness weighted pressure gradient at the
! velocity cell point.
!
! For pressure-like vertical coordinates, we omit the bottom pressure
! and bottom geopotential. Account is taken of variable partial cell
! thickness. 1 = dp/dx; 2 = dp/dy
!
! Thickness weight since this is what we wish to use in update of
! the velocity. Resulting thickness weighted pressure gradient has
! dimensions of Pa = N/m^2 = kg/(m*s^2).
!
! Thickness%dzu should be at tau.
!
!
!
subroutine pressure_gradient_force_press(Time, Thickness, Dens, Velocity, rho)
type(ocean_time_type), intent(in) :: Time
type(ocean_thickness_type), intent(in) :: Thickness
type(ocean_density_type), intent(in) :: Dens
type(ocean_velocity_type), intent(inout) :: Velocity
real, dimension(isd:,jsd:,:), intent(in) :: rho
real, dimension(isd:ied,jsd:jed) :: diff_press_x
real, dimension(isd:ied,jsd:jed) :: diff_press_y
real, dimension(isd:ied,jsd:jed) :: tmp1
real, dimension(isd:ied,jsd:jed) :: tmp2
integer :: i, j, k
integer :: tau
if ( .not. module_is_initialized ) then
call mpp_error(FATAL, &
'==>Error in ocean_pressure_mod (pressure_gradient_force_press): module must be initialized')
endif
tau = Time%tau
tmp1 = 0.0
tmp2 = 0.0
wrk1_v = 0.0
wrk2_v = 0.0
! use density anomaly to improve accuracy
do k=1,nk
do j=jsd,jed
do i=isd,ied
wrk2(i,j,k) = Grd%tmask(i,j,k)*(rho(i,j,k)-rho0)
enddo
enddo
enddo
! compute geopotential anomaly (m^2/s^2) at T-cell point
wrk1(:,:,:) = geopotential_anomaly(Thickness, wrk2(:,:,:))
if(id_anomgeopot > 0) then
used = send_data( id_anomgeopot, wrk1(:,:,:), &
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
diff_press_x(:,:) = 0.0
diff_press_y(:,:) = 0.0
do k=1,nk
do j=jsd,jed
do i=isd,iec
diff_press_x(i,j) = -dbars2pa*(Dens%pressure_at_depth(i+1,j,k)-Dens%pressure_at_depth(i,j,k))
enddo
enddo
do j=jsd,jec
do i=isd,ied
diff_press_y(i,j) = -dbars2pa*(Dens%pressure_at_depth(i,j+1,k)-Dens%pressure_at_depth(i,j,k))
enddo
enddo
! anomalous density times gradient of pressure on k-level
! (dzurhoprime_pgrad_x_klev,dzurhoprime_pgrad_y_klev)
tmp1(:,:) = rho0r*FAY(FAX(wrk2(:,:,k))*diff_press_x(:,:))
tmp2(:,:) = rho0r*FAX(FAY(wrk2(:,:,k))*diff_press_y(:,:))
do j=jsc,jec
do i=isc,iec
wrk1_v(i,j,k,1) = tmp1(i,j)*Grd%dxur(i,j)*Thickness%dzu(i,j,k)
wrk1_v(i,j,k,2) = tmp2(i,j)*Grd%dyur(i,j)*Thickness%dzu(i,j,k)
enddo
enddo
! density times gradient of anomalous geopotential on k-level
! (dzurho_geogradprime_x_klev,dzurho_geogradprime_y_klev)
tmp1(:,:) = FDX_NT(FAY(wrk1(:,:,k)))
tmp2(:,:) = FDY_ET(FAX(wrk1(:,:,k)))
do j=jsc,jec
do i=isc,iec
wrk2_v(i,j,k,1) = tmp1(i,j)*Thickness%rho_dzu(i,j,k,tau)
wrk2_v(i,j,k,2) = tmp2(i,j)*Thickness%rho_dzu(i,j,k,tau)
enddo
enddo
! thickness weighted baroclinic pressure gradient on z-levels
! (dzu_pgrad_u,dzu_pgrad_v)
do j=jsc,jec
do i=isc,iec
Velocity%press_force(i,j,k,1) = -Grd%umask(i,j,k)*( wrk1_v(i,j,k,1) + wrk2_v(i,j,k,1) )
Velocity%press_force(i,j,k,2) = -Grd%umask(i,j,k)*( wrk1_v(i,j,k,2) + wrk2_v(i,j,k,2) )
enddo
enddo
enddo ! k do-loop finish
! (dzurhoprime_pgrad_x_klev,dzurhoprime_pgrad_y_klev)
if (id_rhoprime_pgrad_klev(1) > 0) then
used = send_data(id_rhoprime_pgrad_klev(1),wrk1_v(:,:,:,1), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
if (id_rhoprime_pgrad_klev(2) > 0) then
used = send_data(id_rhoprime_pgrad_klev(2),wrk1_v(:,:,:,2), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
! (dzurho_geogradprime_x_klev,dzurho_geogradprime_y_klev)
if (id_rho_geogradprime_klev(1) > 0) then
used=send_data(id_rho_geogradprime_klev(1),wrk2_v(:,:,:,1), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
if (id_rho_geogradprime_klev(2) > 0) then
used=send_data(id_rho_geogradprime_klev(2),wrk2_v(:,:,:,2), &
Time%model_time, rmask=Grd%umask(:,:,:), &
is_in=isc, js_in=jsc, ks_in=1, ie_in=iec, je_in=jec, ke_in=nk)
endif
end subroutine pressure_gradient_force_press
! NAME="pressure_gradient_force_press"
!#######################################################################
!
!
!
! Compute pressure (dbars) exerted at T cell grid point by weight of
! water column above the grid point.
!
! rho = density in kg/m^3
!
! psurf = surface pressure in Pa= kg/(m*s^2) = hydrostatic pressure
! at z=0 associated with fluid between z=0 and z=eta_t.
! Also include pressure from atmosphere and ice, both of which
! are part of the patm array.
!
! This routine is used by ocean_density to compute the pressure
! used in the equation of state. It is only called when the
! vertical coordinate is DEPTH_BASED.
!
!
function pressure_in_dbars (Thickness, rho, psurf)
type(ocean_thickness_type), intent(in) :: Thickness
real, dimension(isd:,jsd:,:), intent(in) :: rho
real, dimension(isd:,jsd:), intent(in) :: psurf
real, dimension(isd:ied,jsd:jed,nk) :: pressure_in_dbars
integer :: k
if ( .not. module_is_initialized ) then
call mpp_error(FATAL, &
'==>Error in ocean_pressure_mod (pressure_in_dbars): module must be initialized')
endif
pressure_in_dbars(:,:,:) = hydrostatic_pressure (Thickness, rho(:,:,:))*c2dbars
! add pressure from free surface height and loading from atmosphere and/or sea ice
do k=1,nk
pressure_in_dbars(:,:,k) = pressure_in_dbars(:,:,k) + psurf(:,:)*c2dbars
enddo
end function pressure_in_dbars
! NAME="pressure_in_dbars"
!#######################################################################
!
!
!
! Hydrostatic pressure [Pa=N/m^2=kg/(m*s^2)] at T cell grid points.
!
! For GEOPOTENTIAL vertical coordinate, integration is
! from z=0 to depth of grid point. This integration results in
! the so-called "baroclinic" pressure.
!
! For ZSTAR or ZSIGMA, vertical coordinate, integration is from z=eta to
! depth of grid point. This is allowed because ZSTAR and ZSIGMA
! absorb the undulations of the surface height into their definition.
!
! If the input density "rho" is an anomoly, the resulting presure
! will be a hydrostatic pressure anomoly. If "rho" is full density,
! the presure will be a full hydrostatic pressure.
!
!
!
function hydrostatic_pressure (Thickness, rho)
type(ocean_thickness_type), intent(in) :: Thickness
real, dimension(isd:,jsd:,:), intent(in) :: rho
integer :: i, j, k
real, dimension(isd:ied,jsd:jed,nk) :: hydrostatic_pressure
if(vert_coordinate==GEOPOTENTIAL) then
do j=jsd,jed
do i=isd,ied
hydrostatic_pressure(i,j,1) = rho(i,j,1)*grav*Grd%dzw(0)
enddo
enddo
elseif(vert_coordinate==ZSTAR .or. vert_coordinate==ZSIGMA) then
do j=jsd,jed
do i=isd,ied
hydrostatic_pressure(i,j,1) = rho(i,j,1)*grav*Thickness%dzwt(i,j,0)
enddo
enddo
endif
if(Thickness%method==ENERGETIC) then
do k=2,nk
do j=jsd,jed
do i=isd,ied
hydrostatic_pressure(i,j,k) = hydrostatic_pressure(i,j,k-1) &
+ Grd%tmask(i,j,k)*p5grav &
*(rho(i,j,k-1)+rho(i,j,k))*Thickness%dzwt(i,j,k-1)
enddo
enddo
enddo
elseif(Thickness%method==FINITEVOLUME) then
do k=2,nk
do j=jsd,jed
do i=isd,ied
hydrostatic_pressure(i,j,k) = hydrostatic_pressure(i,j,k-1) &
+ Grd%tmask(i,j,k)*grav &
*(Thickness%dztlo(i,j,k-1)*rho(i,j,k-1)+Thickness%dztup(i,j,k)*rho(i,j,k))
enddo
enddo
enddo
endif
! For some debugging...we here drop the contribution from a
! nonzero eta in the calculation of hydrostatic_pressure.
! This is wrong physically, but it is useful for certain tests
! of the zstar vertical coordinate.
if(vert_coordinate==ZSTAR .and. zero_eta_over_h_zstar_pressure) then
do j=jsd,jed
do i=isd,ied
hydrostatic_pressure(i,j,1) = rho(i,j,1)*grav*Thickness%dswt(i,j,0)
enddo
enddo
do k=2,nk
do j=jsd,jed
do i=isd,ied
hydrostatic_pressure(i,j,k) = hydrostatic_pressure(i,j,k-1) &
+ Grd%tmask(i,j,k)*p5grav &
*(rho(i,j,k-1)+rho(i,j,k))*Thickness%dswt(i,j,k-1)
enddo
enddo
enddo
endif
end function hydrostatic_pressure
! NAME="hydrostatic_pressure"
!#######################################################################
!
!
!
! Geopotential anomaly [m^2/s^2] at T cell grid points.
! Integration here is from z=-H to depth of grid point.
!
! Input should be density anomaly rhoprime = rho-rho0.
!
! This function is needed when computing pressure gradient
! for PRESSURE_BASED vertical coordinates.
!
! WARNING: Thickness%method==FINITEVOLUME has been found to be
! problematic. It remains under development. It is NOT
! supported for general use.
!
!
!
function geopotential_anomaly (Thickness, rhoprime)
type(ocean_thickness_type), intent(in) :: Thickness
real, dimension(isd:,jsd:,:), intent(in) :: rhoprime
integer :: i, j, k, kbot
real, dimension(isd:ied,jsd:jed,nk) :: geopotential_anomaly
geopotential_anomaly(:,:,:) = 0.0
if(Thickness%method==ENERGETIC) then
do j=jsd,jed
do i=isd,ied
kbot=Grd%kmt(i,j)
if(kbot > 1) then
k=kbot
geopotential_anomaly(i,j,k) = -grav_rho0r*rhoprime(i,j,k)*Thickness%dzwt(i,j,k)
do k=kbot-1,1,-1
geopotential_anomaly(i,j,k) = geopotential_anomaly(i,j,k+1) &
-p5grav_rho0r*(rhoprime(i,j,k+1)+rhoprime(i,j,k))*Thickness%dzwt(i,j,k)
enddo
endif
enddo
enddo
elseif(Thickness%method==FINITEVOLUME) then
do j=jsd,jed
do i=isd,ied
kbot=Grd%kmt(i,j)
if(kbot > 1) then
k=kbot
geopotential_anomaly(i,j,k) = -grav_rho0r*rhoprime(i,j,k)*Thickness%dztlo(i,j,k)
do k=kbot-1,1,-1
geopotential_anomaly(i,j,k) = geopotential_anomaly(i,j,k+1) &
-grav_rho0r*(Thickness%dztlo(i,j,k)*rhoprime(i,j,k)+Thickness%dztup(i,j,k+1)*rhoprime(i,j,k+1))
enddo
endif
enddo
enddo
endif
end function geopotential_anomaly
! NAME="geopotential_anomaly"
end module ocean_pressure_mod