MOM6
mom_density_integrals Module Reference

Detailed Description

Provides integrals of density.

Functions/Subroutines

subroutine, public int_density_dz (T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, EOS, US, dpa, intz_dpa, intx_dpa, inty_dpa, bathyT, dz_neglect, useMassWghtInterp)
 Calls the appropriate subroutine to calculate analytical and nearly-analytical integrals in z across layers of pressure anomalies, which are required for calculating the finite-volume form pressure accelerations in a Boussinesq model. More...
 
subroutine, public int_density_dz_generic_pcm (T, S, z_t, z_b, rho_ref, rho_0, G_e, HI, EOS, US, dpa, intz_dpa, intx_dpa, inty_dpa, bathyT, dz_neglect, useMassWghtInterp)
 Calculates (by numerical quadrature) integrals of pressure anomalies across layers, which are required for calculating the finite-volume form pressure accelerations in a Boussinesq model. More...
 
subroutine, public int_density_dz_generic_plm (k, tv, T_t, T_b, S_t, S_b, e, rho_ref, rho_0, G_e, dz_subroundoff, bathyT, HI, GV, EOS, US, dpa, intz_dpa, intx_dpa, inty_dpa, useMassWghtInterp)
 Compute pressure gradient force integrals by quadrature for the case where T and S are linear profiles. More...
 
subroutine, public int_density_dz_generic_ppm (k, tv, T_t, T_b, S_t, S_b, e, rho_ref, rho_0, G_e, dz_subroundoff, bathyT, HI, GV, EOS, US, dpa, intz_dpa, intx_dpa, inty_dpa, useMassWghtInterp)
 Compute pressure gradient force integrals for layer "k" and the case where T and S are parabolic profiles. More...
 
subroutine, public int_specific_vol_dp (T, S, p_t, p_b, alpha_ref, HI, EOS, US, dza, intp_dza, intx_dza, inty_dza, halo_size, bathyP, dP_tiny, useMassWghtInterp)
 Calls the appropriate subroutine to calculate analytical and nearly-analytical integrals in pressure across layers of geopotential anomalies, which are required for calculating the finite-volume form pressure accelerations in a non-Boussinesq model. There are essentially no free assumptions, apart from the use of Boole's rule to do the horizontal integrals, and from a truncation in the series for log(1-eps/1+eps) that assumes that |eps| < 0.34. More...
 
subroutine, public int_spec_vol_dp_generic_pcm (T, S, p_t, p_b, alpha_ref, HI, EOS, US, dza, intp_dza, intx_dza, inty_dza, halo_size, bathyP, dP_neglect, useMassWghtInterp)
 This subroutine calculates integrals of specific volume anomalies in pressure across layers, which are required for calculating the finite-volume form pressure accelerations in a non-Boussinesq model. There are essentially no free assumptions, apart from the use of Boole's rule quadrature to do the integrals. More...
 
subroutine, public int_spec_vol_dp_generic_plm (T_t, T_b, S_t, S_b, p_t, p_b, alpha_ref, dP_neglect, bathyP, HI, EOS, US, dza, intp_dza, intx_dza, inty_dza, useMassWghtInterp)
 This subroutine calculates integrals of specific volume anomalies in pressure across layers, which are required for calculating the finite-volume form pressure accelerations in a non-Boussinesq model. There are essentially no free assumptions, apart from the use of Boole's rule quadrature to do the integrals. More...
 
subroutine, public find_depth_of_pressure_in_cell (T_t, T_b, S_t, S_b, z_t, z_b, P_t, P_tgt, rho_ref, G_e, EOS, US, P_b, z_out, z_tol)
 Find the depth at which the reconstructed pressure matches P_tgt. More...
 
real function frac_dp_at_pos (T_t, T_b, S_t, S_b, z_t, z_b, rho_ref, G_e, pos, EOS)
 Returns change in anomalous pressure change from top to non-dimensional position pos between z_t and z_b. More...
 

Function/Subroutine Documentation

◆ find_depth_of_pressure_in_cell()

subroutine, public mom_density_integrals::find_depth_of_pressure_in_cell ( real, intent(in)  T_t,
real, intent(in)  T_b,
real, intent(in)  S_t,
real, intent(in)  S_b,
real, intent(in)  z_t,
real, intent(in)  z_b,
real, intent(in)  P_t,
real, intent(in)  P_tgt,
real, intent(in)  rho_ref,
real, intent(in)  G_e,
type(eos_type), pointer  EOS,
type(unit_scale_type), intent(in)  US,
real, intent(out)  P_b,
real, intent(out)  z_out,
real, intent(in), optional  z_tol 
)

Find the depth at which the reconstructed pressure matches P_tgt.

Parameters
[in]t_tPotential temperature at the cell top [degC]
[in]t_bPotential temperature at the cell bottom [degC]
[in]s_tSalinity at the cell top [ppt]
[in]s_bSalinity at the cell bottom [ppt]
[in]z_tAbsolute height of top of cell [Z ~> m] (Boussinesq ????)
[in]z_bAbsolute height of bottom of cell [Z ~> m]
[in]p_tAnomalous pressure of top of cell, relative to g*rho_ref*z_t [R L2 T-2 ~> Pa]
[in]p_tgtTarget pressure at height z_out, relative to g*rho_ref*z_out [R L2 T-2 ~> Pa]
[in]rho_refReference density with which calculation are anomalous to [R ~> kg m-3]
[in]g_eGravitational acceleration [L2 Z-1 T-2 ~> m s-2]
eosEquation of state structure
[in]usA dimensional unit scaling type
[out]p_bPressure at the bottom of the cell [R L2 T-2 ~> Pa]
[out]z_outAbsolute depth at which anomalous pressure = p_tgt [Z ~> m]
[in]z_tolThe tolerance in finding z_out [Z ~> m]

Definition at line 1527 of file MOM_density_integrals.F90.

1527  real, intent(in) :: T_t !< Potential temperature at the cell top [degC]
1528  real, intent(in) :: T_b !< Potential temperature at the cell bottom [degC]
1529  real, intent(in) :: S_t !< Salinity at the cell top [ppt]
1530  real, intent(in) :: S_b !< Salinity at the cell bottom [ppt]
1531  real, intent(in) :: z_t !< Absolute height of top of cell [Z ~> m] (Boussinesq ????)
1532  real, intent(in) :: z_b !< Absolute height of bottom of cell [Z ~> m]
1533  real, intent(in) :: P_t !< Anomalous pressure of top of cell, relative
1534  !! to g*rho_ref*z_t [R L2 T-2 ~> Pa]
1535  real, intent(in) :: P_tgt !< Target pressure at height z_out, relative
1536  !! to g*rho_ref*z_out [R L2 T-2 ~> Pa]
1537  real, intent(in) :: rho_ref !< Reference density with which calculation
1538  !! are anomalous to [R ~> kg m-3]
1539  real, intent(in) :: G_e !< Gravitational acceleration [L2 Z-1 T-2 ~> m s-2]
1540  type(EOS_type), pointer :: EOS !< Equation of state structure
1541  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
1542  real, intent(out) :: P_b !< Pressure at the bottom of the cell [R L2 T-2 ~> Pa]
1543  real, intent(out) :: z_out !< Absolute depth at which anomalous pressure = p_tgt [Z ~> m]
1544  real, optional, intent(in) :: z_tol !< The tolerance in finding z_out [Z ~> m]
1545 
1546  ! Local variables
1547  real :: dp ! Pressure thickness of the layer [R L2 T-2 ~> Pa]
1548  real :: F_guess, F_l, F_r ! Fractional positions [nondim]
1549  real :: GxRho ! The product of the gravitational acceleration and reference density [R L2 Z-1 T-2 ~> Pa m-1]
1550  real :: Pa, Pa_left, Pa_right, Pa_tol ! Pressure anomalies, P = integral of g*(rho-rho_ref) dz [R L2 T-2 ~> Pa]
1551  character(len=240) :: msg
1552 
1553  gxrho = g_e * rho_ref
1554 
1555  ! Anomalous pressure difference across whole cell
1556  dp = frac_dp_at_pos(t_t, t_b, s_t, s_b, z_t, z_b, rho_ref, g_e, 1.0, eos)
1557 
1558  p_b = p_t + dp ! Anomalous pressure at bottom of cell
1559 
1560  if (p_tgt <= p_t ) then
1561  z_out = z_t
1562  return
1563  endif
1564 
1565  if (p_tgt >= p_b) then
1566  z_out = z_b
1567  return
1568  endif
1569 
1570  f_l = 0.
1571  pa_left = p_t - p_tgt ! Pa_left < 0
1572  f_r = 1.
1573  pa_right = p_b - p_tgt ! Pa_right > 0
1574  pa_tol = gxrho * 1.0e-5*us%m_to_Z
1575  if (present(z_tol)) pa_tol = gxrho * z_tol
1576 
1577  f_guess = f_l - pa_left / (pa_right - pa_left) * (f_r - f_l)
1578  pa = pa_right - pa_left ! To get into iterative loop
1579  do while ( abs(pa) > pa_tol )
1580 
1581  z_out = z_t + ( z_b - z_t ) * f_guess
1582  pa = frac_dp_at_pos(t_t, t_b, s_t, s_b, z_t, z_b, rho_ref, g_e, f_guess, eos) - ( p_tgt - p_t )
1583 
1584  if (pa<pa_left) then
1585  write(msg,*) pa_left,pa,pa_right,p_t-p_tgt,p_b-p_tgt
1586  call mom_error(fatal, 'find_depth_of_pressure_in_cell out of bounds negative: /n'//msg)
1587  elseif (pa<0.) then
1588  pa_left = pa
1589  f_l = f_guess
1590  elseif (pa>pa_right) then
1591  write(msg,*) pa_left,pa,pa_right,p_t-p_tgt,p_b-p_tgt
1592  call mom_error(fatal, 'find_depth_of_pressure_in_cell out of bounds positive: /n'//msg)
1593  elseif (pa>0.) then
1594  pa_right = pa
1595  f_r = f_guess
1596  else ! Pa == 0
1597  return
1598  endif
1599  f_guess = f_l - pa_left / (pa_right - pa_left) * (f_r - f_l)
1600 
1601  enddo
1602 

◆ frac_dp_at_pos()

real function mom_density_integrals::frac_dp_at_pos ( real, intent(in)  T_t,
real, intent(in)  T_b,
real, intent(in)  S_t,
real, intent(in)  S_b,
real, intent(in)  z_t,
real, intent(in)  z_b,
real, intent(in)  rho_ref,
real, intent(in)  G_e,
real, intent(in)  pos,
type(eos_type), pointer  EOS 
)
private

Returns change in anomalous pressure change from top to non-dimensional position pos between z_t and z_b.

Parameters
[in]t_tPotential temperature at the cell top [degC]
[in]t_bPotential temperature at the cell bottom [degC]
[in]s_tSalinity at the cell top [ppt]
[in]s_bSalinity at the cell bottom [ppt]
[in]z_tThe geometric height at the top of the layer [Z ~> m]
[in]z_bThe geometric height at the bottom of the layer [Z ~> m]
[in]rho_refA mean density [R ~> kg m-3], that is subtracted out to reduce the magnitude of each of the integrals.
[in]g_eThe Earth's gravitational acceleration [L2 Z-1 T-2 ~> m s-2]
[in]posThe fractional vertical position, 0 to 1 [nondim]
eosEquation of state structure

Definition at line 1609 of file MOM_density_integrals.F90.

1609  real, intent(in) :: T_t !< Potential temperature at the cell top [degC]
1610  real, intent(in) :: T_b !< Potential temperature at the cell bottom [degC]
1611  real, intent(in) :: S_t !< Salinity at the cell top [ppt]
1612  real, intent(in) :: S_b !< Salinity at the cell bottom [ppt]
1613  real, intent(in) :: z_t !< The geometric height at the top of the layer [Z ~> m]
1614  real, intent(in) :: z_b !< The geometric height at the bottom of the layer [Z ~> m]
1615  real, intent(in) :: rho_ref !< A mean density [R ~> kg m-3], that is subtracted out to
1616  !! reduce the magnitude of each of the integrals.
1617  real, intent(in) :: G_e !< The Earth's gravitational acceleration [L2 Z-1 T-2 ~> m s-2]
1618  real, intent(in) :: pos !< The fractional vertical position, 0 to 1 [nondim]
1619  type(EOS_type), pointer :: EOS !< Equation of state structure
1620  real :: fract_dp_at_pos !< The change in pressure from the layer top to
1621  !! fractional position pos [R L2 T-2 ~> Pa]
1622  ! Local variables
1623  real, parameter :: C1_90 = 1.0/90.0 ! A rational constant [nondim]
1624  real :: dz ! Distance from the layer top [Z ~> m]
1625  real :: top_weight, bottom_weight ! Fractional weights at quadrature points [nondim]
1626  real :: rho_ave ! Average density [R ~> kg m-3]
1627  real, dimension(5) :: T5 ! Temperatures at quadrature points [degC]
1628  real, dimension(5) :: S5 ! Salinities at quadrature points [ppt]
1629  real, dimension(5) :: p5 ! Pressures at quadrature points [R L2 T-2 ~> Pa]
1630  real, dimension(5) :: rho5 ! Densities at quadrature points [R ~> kg m-3]
1631  integer :: n
1632 
1633  do n=1,5
1634  ! Evaluate density at five quadrature points
1635  bottom_weight = 0.25*real(n-1) * pos
1636  top_weight = 1.0 - bottom_weight
1637  ! Salinity and temperature points are linearly interpolated
1638  s5(n) = top_weight * s_t + bottom_weight * s_b
1639  t5(n) = top_weight * t_t + bottom_weight * t_b
1640  p5(n) = ( top_weight * z_t + bottom_weight * z_b ) * ( g_e * rho_ref )
1641  enddo
1642  call calculate_density(t5, s5, p5, rho5, eos)
1643  rho5(:) = rho5(:) !- rho_ref ! Work with anomalies relative to rho_ref
1644 
1645  ! Use Boole's rule to estimate the average density
1646  rho_ave = c1_90*(7.0*(rho5(1)+rho5(5)) + 32.0*(rho5(2)+rho5(4)) + 12.0*rho5(3))
1647 
1648  dz = ( z_t - z_b ) * pos
1649  frac_dp_at_pos = g_e * dz * rho_ave

◆ int_density_dz()

subroutine, public mom_density_integrals::int_density_dz ( real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  T,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  S,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  z_t,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  z_b,
real, intent(in)  rho_ref,
real, intent(in)  rho_0,
real, intent(in)  G_e,
type(hor_index_type), intent(in)  HI,
type(eos_type), pointer  EOS,
type(unit_scale_type), intent(in)  US,
real, dimension(szi_(hi),szj_(hi)), intent(inout)  dpa,
real, dimension(szi_(hi),szj_(hi)), intent(inout), optional  intz_dpa,
real, dimension(szib_(hi),szj_(hi)), intent(inout), optional  intx_dpa,
real, dimension(szi_(hi),szjb_(hi)), intent(inout), optional  inty_dpa,
real, dimension(szi_(hi),szj_(hi)), intent(in), optional  bathyT,
real, intent(in), optional  dz_neglect,
logical, intent(in), optional  useMassWghtInterp 
)

Calls the appropriate subroutine to calculate analytical and nearly-analytical integrals in z across layers of pressure anomalies, which are required for calculating the finite-volume form pressure accelerations in a Boussinesq model.

Parameters
[in]hiOcean horizontal index structures for the arrays
[in]tPotential temperature referenced to the surface [degC]
[in]sSalinity [ppt]
[in]z_tHeight at the top of the layer in depth units [Z ~> m]
[in]z_bHeight at the bottom of the layer [Z ~> m]
[in]rho_refA mean density [R ~> kg m-3] or [kg m-3], that is subtracted out to reduce the magnitude of each of the integrals.
[in]rho_0A density [R ~> kg m-3] or [kg m-3], that is used to calculate the pressure (as p~=-z*rho_0*G_e) used in the equation of state.
[in]g_eThe Earth's gravitational acceleration [L2 Z-1 T-2 ~> m s-2] or [m2 Z-1 s-2 ~> m s-2]
eosEquation of state structure
[in]usA dimensional unit scaling type
[in,out]dpaThe change in the pressure anomaly
[in,out]intz_dpaThe integral through the thickness of the
[in,out]intx_dpaThe integral in x of the difference between
[in,out]inty_dpaThe integral in y of the difference between
[in]bathytThe depth of the bathymetry [Z ~> m]
[in]dz_neglectA minuscule thickness change [Z ~> m]
[in]usemasswghtinterpIf true, uses mass weighting to interpolate T/S for top and bottom integrals.

Definition at line 42 of file MOM_density_integrals.F90.

42  type(hor_index_type), intent(in) :: HI !< Ocean horizontal index structures for the arrays
43  real, dimension(SZI_(HI),SZJ_(HI)), &
44  intent(in) :: T !< Potential temperature referenced to the surface [degC]
45  real, dimension(SZI_(HI),SZJ_(HI)), &
46  intent(in) :: S !< Salinity [ppt]
47  real, dimension(SZI_(HI),SZJ_(HI)), &
48  intent(in) :: z_t !< Height at the top of the layer in depth units [Z ~> m]
49  real, dimension(SZI_(HI),SZJ_(HI)), &
50  intent(in) :: z_b !< Height at the bottom of the layer [Z ~> m]
51  real, intent(in) :: rho_ref !< A mean density [R ~> kg m-3] or [kg m-3], that is
52  !! subtracted out to reduce the magnitude of each of the
53  !! integrals.
54  real, intent(in) :: rho_0 !< A density [R ~> kg m-3] or [kg m-3], that is used
55  !! to calculate the pressure (as p~=-z*rho_0*G_e)
56  !! used in the equation of state.
57  real, intent(in) :: G_e !< The Earth's gravitational acceleration
58  !! [L2 Z-1 T-2 ~> m s-2] or [m2 Z-1 s-2 ~> m s-2]
59  type(EOS_type), pointer :: EOS !< Equation of state structure
60  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
61  real, dimension(SZI_(HI),SZJ_(HI)), &
62  intent(inout) :: dpa !< The change in the pressure anomaly
63  !! across the layer [R L2 T-2 ~> Pa] or [Pa]
64  real, dimension(SZI_(HI),SZJ_(HI)), &
65  optional, intent(inout) :: intz_dpa !< The integral through the thickness of the
66  !! layer of the pressure anomaly relative to the
67  !! anomaly at the top of the layer [R L2 Z T-2 ~> Pa m]
68  real, dimension(SZIB_(HI),SZJ_(HI)), &
69  optional, intent(inout) :: intx_dpa !< The integral in x of the difference between
70  !! the pressure anomaly at the top and bottom of the
71  !! layer divided by the x grid spacing [R L2 T-2 ~> Pa]
72  real, dimension(SZI_(HI),SZJB_(HI)), &
73  optional, intent(inout) :: inty_dpa !< The integral in y of the difference between
74  !! the pressure anomaly at the top and bottom of the
75  !! layer divided by the y grid spacing [R L2 T-2 ~> Pa]
76  real, dimension(SZI_(HI),SZJ_(HI)), &
77  optional, intent(in) :: bathyT !< The depth of the bathymetry [Z ~> m]
78  real, optional, intent(in) :: dz_neglect !< A minuscule thickness change [Z ~> m]
79  logical, optional, intent(in) :: useMassWghtInterp !< If true, uses mass weighting to
80  !! interpolate T/S for top and bottom integrals.
81 
82  if (eos_quadrature(eos)) then
83  call int_density_dz_generic_pcm(t, s, z_t, z_b, rho_ref, rho_0, g_e, hi, eos, us, dpa, &
84  intz_dpa, intx_dpa, inty_dpa, bathyt, dz_neglect, usemasswghtinterp)
85  else
86  call analytic_int_density_dz(t, s, z_t, z_b, rho_ref, rho_0, g_e, hi, eos, dpa, &
87  intz_dpa, intx_dpa, inty_dpa, bathyt, dz_neglect, usemasswghtinterp)
88  endif
89 

◆ int_density_dz_generic_pcm()

subroutine, public mom_density_integrals::int_density_dz_generic_pcm ( real, dimension(szi_(hi),szj_(hi)), intent(in)  T,
real, dimension(szi_(hi),szj_(hi)), intent(in)  S,
real, dimension(szi_(hi),szj_(hi)), intent(in)  z_t,
real, dimension(szi_(hi),szj_(hi)), intent(in)  z_b,
real, intent(in)  rho_ref,
real, intent(in)  rho_0,
real, intent(in)  G_e,
type(hor_index_type), intent(in)  HI,
type(eos_type), pointer  EOS,
type(unit_scale_type), intent(in)  US,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(inout)  dpa,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(inout), optional  intz_dpa,
real, dimension( hi %isdb: hi %iedb, hi %jsd: hi %jed), intent(inout), optional  intx_dpa,
real, dimension( hi %isd: hi %ied, hi %jsdb: hi %jedb), intent(inout), optional  inty_dpa,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in), optional  bathyT,
real, intent(in), optional  dz_neglect,
logical, intent(in), optional  useMassWghtInterp 
)

Calculates (by numerical quadrature) integrals of pressure anomalies across layers, which are required for calculating the finite-volume form pressure accelerations in a Boussinesq model.

Parameters
[in]hiHorizontal index type for input variables.
[in]tPotential temperature of the layer [degC]
[in]sSalinity of the layer [ppt]
[in]z_tHeight at the top of the layer in depth units [Z ~> m]
[in]z_bHeight at the bottom of the layer [Z ~> m]
[in]rho_refA mean density [R ~> kg m-3] or [kg m-3], that is subtracted out to reduce the magnitude of each of the integrals.
[in]rho_0A density [R ~> kg m-3] or [kg m-3], that is used to calculate the pressure (as p~=-z*rho_0*G_e) used in the equation of state.
[in]g_eThe Earth's gravitational acceleration [L2 Z-1 T-2 ~> m s-2] or [m2 Z-1 s-2 ~> m s-2]
eosEquation of state structure
[in]usA dimensional unit scaling type
[in,out]dpaThe change in the pressure anomaly
[in,out]intz_dpaThe integral through the thickness of the
[in,out]intx_dpaThe integral in x of the difference between
[in,out]inty_dpaThe integral in y of the difference between
[in]bathytThe depth of the bathymetry [Z ~> m]
[in]dz_neglectA minuscule thickness change [Z ~> m]
[in]usemasswghtinterpIf true, uses mass weighting to interpolate T/S for top and bottom integrals.

Definition at line 98 of file MOM_density_integrals.F90.

98  type(hor_index_type), intent(in) :: HI !< Horizontal index type for input variables.
99  real, dimension(SZI_(HI),SZJ_(HI)), &
100  intent(in) :: T !< Potential temperature of the layer [degC]
101  real, dimension(SZI_(HI),SZJ_(HI)), &
102  intent(in) :: S !< Salinity of the layer [ppt]
103  real, dimension(SZI_(HI),SZJ_(HI)), &
104  intent(in) :: z_t !< Height at the top of the layer in depth units [Z ~> m]
105  real, dimension(SZI_(HI),SZJ_(HI)), &
106  intent(in) :: z_b !< Height at the bottom of the layer [Z ~> m]
107  real, intent(in) :: rho_ref !< A mean density [R ~> kg m-3] or [kg m-3], that is
108  !! subtracted out to reduce the magnitude
109  !! of each of the integrals.
110  real, intent(in) :: rho_0 !< A density [R ~> kg m-3] or [kg m-3], that is used
111  !! to calculate the pressure (as p~=-z*rho_0*G_e)
112  !! used in the equation of state.
113  real, intent(in) :: G_e !< The Earth's gravitational acceleration
114  !! [L2 Z-1 T-2 ~> m s-2] or [m2 Z-1 s-2 ~> m s-2]
115  type(EOS_type), pointer :: EOS !< Equation of state structure
116  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
117  real, dimension(SZI_(HI),SZJ_(HI)), &
118  intent(inout) :: dpa !< The change in the pressure anomaly
119  !! across the layer [R L2 T-2 ~> Pa] or [Pa]
120  real, dimension(SZI_(HI),SZJ_(HI)), &
121  optional, intent(inout) :: intz_dpa !< The integral through the thickness of the
122  !! layer of the pressure anomaly relative to the
123  !! anomaly at the top of the layer [R L2 Z T-2 ~> Pa m]
124  real, dimension(SZIB_(HI),SZJ_(HI)), &
125  optional, intent(inout) :: intx_dpa !< The integral in x of the difference between
126  !! the pressure anomaly at the top and bottom of the
127  !! layer divided by the x grid spacing [R L2 T-2 ~> Pa]
128  real, dimension(SZI_(HI),SZJB_(HI)), &
129  optional, intent(inout) :: inty_dpa !< The integral in y of the difference between
130  !! the pressure anomaly at the top and bottom of the
131  !! layer divided by the y grid spacing [R L2 T-2 ~> Pa]
132  real, dimension(SZI_(HI),SZJ_(HI)), &
133  optional, intent(in) :: bathyT !< The depth of the bathymetry [Z ~> m]
134  real, optional, intent(in) :: dz_neglect !< A minuscule thickness change [Z ~> m]
135  logical, optional, intent(in) :: useMassWghtInterp !< If true, uses mass weighting to
136  !! interpolate T/S for top and bottom integrals.
137  ! Local variables
138  real :: T5(5), S5(5) ! Temperatures and salinities at five quadrature points [degC] and [ppt]
139  real :: p5(5) ! Pressures at five quadrature points, never rescaled from Pa [Pa]
140  real :: r5(5) ! Densities at five quadrature points [R ~> kg m-3] or [kg m-3]
141  real :: rho_anom ! The depth averaged density anomaly [R ~> kg m-3] or [kg m-3]
142  real :: w_left, w_right ! Left and right weights [nondim]
143  real, parameter :: C1_90 = 1.0/90.0 ! Rational constants.
144  real :: GxRho ! The gravitational acceleration times density and unit conversion factors [Pa Z-1 ~> kg m-2 s-2]
145  real :: I_Rho ! The inverse of the Boussinesq density [R-1 ~> m3 kg-1] or [m3 kg-1]
146  real :: rho_scale ! A scaling factor for densities from kg m-3 to R [R m3 kg-1 ~> 1]
147  real :: rho_ref_mks ! The reference density in MKS units, never rescaled from kg m-3 [kg m-3]
148  real :: dz ! The layer thickness [Z ~> m]
149  real :: hWght ! A pressure-thickness below topography [Z ~> m]
150  real :: hL, hR ! Pressure-thicknesses of the columns to the left and right [Z ~> m]
151  real :: iDenom ! The inverse of the denominator in the weights [Z-2 ~> m-2]
152  real :: hWt_LL, hWt_LR ! hWt_LA is the weighted influence of A on the left column [nondim]
153  real :: hWt_RL, hWt_RR ! hWt_RA is the weighted influence of A on the right column [nondim]
154  real :: wt_L, wt_R ! The linear weights of the left and right columns [nondim]
155  real :: wtT_L, wtT_R ! The weights for tracers from the left and right columns [nondim]
156  real :: intz(5) ! The gravitational acceleration times the integrals of density
157  ! with height at the 5 sub-column locations [R L2 T-2 ~> Pa] or [Pa]
158  logical :: do_massWeight ! Indicates whether to do mass weighting.
159  integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, i, j, m, n
160 
161  ! These array bounds work for the indexing convention of the input arrays, but
162  ! on the computational domain defined for the output arrays.
163  isq = hi%IscB ; ieq = hi%IecB
164  jsq = hi%JscB ; jeq = hi%JecB
165  is = hi%isc ; ie = hi%iec
166  js = hi%jsc ; je = hi%jec
167 
168  rho_scale = us%kg_m3_to_R
169  gxrho = us%RL2_T2_to_Pa * g_e * rho_0
170  rho_ref_mks = rho_ref * us%R_to_kg_m3
171  i_rho = 1.0 / rho_0
172 
173  do_massweight = .false.
174  if (present(usemasswghtinterp)) then ; if (usemasswghtinterp) then
175  do_massweight = .true.
176  if (.not.present(bathyt)) call mom_error(fatal, "int_density_dz_generic: "//&
177  "bathyT must be present if useMassWghtInterp is present and true.")
178  if (.not.present(dz_neglect)) call mom_error(fatal, "int_density_dz_generic: "//&
179  "dz_neglect must be present if useMassWghtInterp is present and true.")
180  endif ; endif
181 
182  do j=jsq,jeq+1 ; do i=isq,ieq+1
183  dz = z_t(i,j) - z_b(i,j)
184  do n=1,5
185  t5(n) = t(i,j) ; s5(n) = s(i,j)
186  p5(n) = -gxrho*(z_t(i,j) - 0.25*real(n-1)*dz)
187  enddo
188  if (rho_scale /= 1.0) then
189  call calculate_density(t5, s5, p5, r5, 1, 5, eos, rho_ref=rho_ref_mks, scale=rho_scale)
190  else
191  call calculate_density(t5, s5, p5, r5, 1, 5, eos, rho_ref=rho_ref_mks)
192  endif
193 
194  ! Use Boole's rule to estimate the pressure anomaly change.
195  rho_anom = c1_90*(7.0*(r5(1)+r5(5)) + 32.0*(r5(2)+r5(4)) + 12.0*r5(3))
196  dpa(i,j) = g_e*dz*rho_anom
197  ! Use a Boole's-rule-like fifth-order accurate estimate of the double integral of
198  ! the pressure anomaly.
199  if (present(intz_dpa)) intz_dpa(i,j) = 0.5*g_e*dz**2 * &
200  (rho_anom - c1_90*(16.0*(r5(4)-r5(2)) + 7.0*(r5(5)-r5(1))) )
201  enddo ; enddo
202 
203  if (present(intx_dpa)) then ; do j=js,je ; do i=isq,ieq
204  ! hWght is the distance measure by which the cell is violation of
205  ! hydrostatic consistency. For large hWght we bias the interpolation of
206  ! T & S along the top and bottom integrals, akin to thickness weighting.
207  hwght = 0.0
208  if (do_massweight) &
209  hwght = max(0., -bathyt(i,j)-z_t(i+1,j), -bathyt(i+1,j)-z_t(i,j))
210  if (hwght > 0.) then
211  hl = (z_t(i,j) - z_b(i,j)) + dz_neglect
212  hr = (z_t(i+1,j) - z_b(i+1,j)) + dz_neglect
213  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
214  idenom = 1.0 / ( hwght*(hr + hl) + hl*hr )
215  hwt_ll = (hwght*hl + hr*hl) * idenom ; hwt_lr = (hwght*hr) * idenom
216  hwt_rr = (hwght*hr + hr*hl) * idenom ; hwt_rl = (hwght*hl) * idenom
217  else
218  hwt_ll = 1.0 ; hwt_lr = 0.0 ; hwt_rr = 1.0 ; hwt_rl = 0.0
219  endif
220 
221  intz(1) = dpa(i,j) ; intz(5) = dpa(i+1,j)
222  do m=2,4
223  ! T, S, and z are interpolated in the horizontal. The z interpolation
224  ! is linear, but for T and S it may be thickness weighted.
225  wt_l = 0.25*real(5-m) ; wt_r = 1.0-wt_l
226  wtt_l = wt_l*hwt_ll + wt_r*hwt_rl ; wtt_r = wt_l*hwt_lr + wt_r*hwt_rr
227  dz = wt_l*(z_t(i,j) - z_b(i,j)) + wt_r*(z_t(i+1,j) - z_b(i+1,j))
228  t5(1) = wtt_l*t(i,j) + wtt_r*t(i+1,j)
229  s5(1) = wtt_l*s(i,j) + wtt_r*s(i+1,j)
230  p5(1) = -gxrho*(wt_l*z_t(i,j) + wt_r*z_t(i+1,j))
231  do n=2,5
232  t5(n) = t5(1) ; s5(n) = s5(1) ; p5(n) = p5(n-1) + gxrho*0.25*dz
233  enddo
234  if (rho_scale /= 1.0) then
235  call calculate_density(t5, s5, p5, r5, 1, 5, eos, rho_ref=rho_ref_mks, scale=rho_scale)
236  else
237  call calculate_density(t5, s5, p5, r5, 1, 5, eos, rho_ref=rho_ref_mks)
238  endif
239 
240  ! Use Boole's rule to estimate the pressure anomaly change.
241  intz(m) = g_e*dz*( c1_90*(7.0*(r5(1)+r5(5)) + 32.0*(r5(2)+r5(4)) + 12.0*r5(3)))
242  enddo
243  ! Use Boole's rule to integrate the bottom pressure anomaly values in x.
244  intx_dpa(i,j) = c1_90*(7.0*(intz(1)+intz(5)) + 32.0*(intz(2)+intz(4)) + &
245  12.0*intz(3))
246  enddo ; enddo ; endif
247 
248  if (present(inty_dpa)) then ; do j=jsq,jeq ; do i=is,ie
249  ! hWght is the distance measure by which the cell is violation of
250  ! hydrostatic consistency. For large hWght we bias the interpolation of
251  ! T & S along the top and bottom integrals, akin to thickness weighting.
252  hwght = 0.0
253  if (do_massweight) &
254  hwght = max(0., -bathyt(i,j)-z_t(i,j+1), -bathyt(i,j+1)-z_t(i,j))
255  if (hwght > 0.) then
256  hl = (z_t(i,j) - z_b(i,j)) + dz_neglect
257  hr = (z_t(i,j+1) - z_b(i,j+1)) + dz_neglect
258  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
259  idenom = 1.0 / ( hwght*(hr + hl) + hl*hr )
260  hwt_ll = (hwght*hl + hr*hl) * idenom ; hwt_lr = (hwght*hr) * idenom
261  hwt_rr = (hwght*hr + hr*hl) * idenom ; hwt_rl = (hwght*hl) * idenom
262  else
263  hwt_ll = 1.0 ; hwt_lr = 0.0 ; hwt_rr = 1.0 ; hwt_rl = 0.0
264  endif
265 
266  intz(1) = dpa(i,j) ; intz(5) = dpa(i,j+1)
267  do m=2,4
268  ! T, S, and z are interpolated in the horizontal. The z interpolation
269  ! is linear, but for T and S it may be thickness weighted.
270  wt_l = 0.25*real(5-m) ; wt_r = 1.0-wt_l
271  wtt_l = wt_l*hwt_ll + wt_r*hwt_rl ; wtt_r = wt_l*hwt_lr + wt_r*hwt_rr
272  dz = wt_l*(z_t(i,j) - z_b(i,j)) + wt_r*(z_t(i,j+1) - z_b(i,j+1))
273  t5(1) = wtt_l*t(i,j) + wtt_r*t(i,j+1)
274  s5(1) = wtt_l*s(i,j) + wtt_r*s(i,j+1)
275  p5(1) = -gxrho*(wt_l*z_t(i,j) + wt_r*z_t(i,j+1))
276  do n=2,5
277  t5(n) = t5(1) ; s5(n) = s5(1)
278  p5(n) = p5(n-1) + gxrho*0.25*dz
279  enddo
280  if (rho_scale /= 1.0) then
281  call calculate_density(t5, s5, p5, r5, 1, 5, eos, rho_ref=rho_ref_mks, scale=rho_scale)
282  else
283  call calculate_density(t5, s5, p5, r5, 1, 5, eos, rho_ref=rho_ref_mks)
284  endif
285 
286  ! Use Boole's rule to estimate the pressure anomaly change.
287  intz(m) = g_e*dz*( c1_90*(7.0*(r5(1)+r5(5)) + 32.0*(r5(2)+r5(4)) + 12.0*r5(3)))
288  enddo
289  ! Use Boole's rule to integrate the values.
290  inty_dpa(i,j) = c1_90*(7.0*(intz(1)+intz(5)) + 32.0*(intz(2)+intz(4)) + &
291  12.0*intz(3))
292  enddo ; enddo ; endif

◆ int_density_dz_generic_plm()

subroutine, public mom_density_integrals::int_density_dz_generic_plm ( integer, intent(in)  k,
type(thermo_var_ptrs), intent(in)  tv,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed, gv %ke), intent(in)  T_t,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed, gv %ke), intent(in)  T_b,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed, gv %ke), intent(in)  S_t,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed, gv %ke), intent(in)  S_b,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed, gv %ke+1), intent(in)  e,
real, intent(in)  rho_ref,
real, intent(in)  rho_0,
real, intent(in)  G_e,
real, intent(in)  dz_subroundoff,
real, dimension(szi_(hi),szj_(hi)), intent(in)  bathyT,
type(hor_index_type), intent(in)  HI,
type(verticalgrid_type), intent(in)  GV,
type(eos_type), pointer  EOS,
type(unit_scale_type), intent(in)  US,
real, dimension(szi_(hi),szj_(hi)), intent(inout)  dpa,
real, dimension(szi_(hi),szj_(hi)), intent(inout), optional  intz_dpa,
real, dimension(szib_(hi),szj_(hi)), intent(inout), optional  intx_dpa,
real, dimension(szi_(hi),szjb_(hi)), intent(inout), optional  inty_dpa,
logical, intent(in), optional  useMassWghtInterp 
)

Compute pressure gradient force integrals by quadrature for the case where T and S are linear profiles.

Parameters
[in]kLayer index to calculate integrals for
[in]hiOcean horizontal index structures for the input arrays
[in]gvVertical grid structure
[in]tvThermodynamic variables
[in]t_tPotential temperature at the cell top [degC]
[in]t_bPotential temperature at the cell bottom [degC]
[in]s_tSalinity at the cell top [ppt]
[in]s_bSalinity at the cell bottom [ppt]
[in]eHeight of interfaces [Z ~> m]
[in]rho_refA mean density [R ~> kg m-3] or [kg m-3], that is subtracted out to reduce the magnitude of each of the integrals.
[in]rho_0A density [R ~> kg m-3] or [kg m-3], that is used to calculate the pressure (as p~=-z*rho_0*G_e) used in the equation of state.
[in]g_eThe Earth's gravitational acceleration [L2 Z-1 T-2 ~> m s-2]
[in]dz_subroundoffA minuscule thickness change [Z ~> m]
[in]bathytThe depth of the bathymetry [Z ~> m]
eosEquation of state structure
[in]usA dimensional unit scaling type
[in,out]dpaThe change in the pressure anomaly across the layer [R L2 T-2 ~> Pa]
[in,out]intz_dpaThe integral through the thickness of the layer of
[in,out]intx_dpaThe integral in x of the difference between the
[in,out]inty_dpaThe integral in y of the difference between the
[in]usemasswghtinterpIf true, uses mass weighting to interpolate T/S for top and bottom integrals.

Definition at line 301 of file MOM_density_integrals.F90.

301  integer, intent(in) :: k !< Layer index to calculate integrals for
302  type(hor_index_type), intent(in) :: HI !< Ocean horizontal index structures for the input arrays
303  type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure
304  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables
305  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), &
306  intent(in) :: T_t !< Potential temperature at the cell top [degC]
307  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), &
308  intent(in) :: T_b !< Potential temperature at the cell bottom [degC]
309  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), &
310  intent(in) :: S_t !< Salinity at the cell top [ppt]
311  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), &
312  intent(in) :: S_b !< Salinity at the cell bottom [ppt]
313  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)+1), &
314  intent(in) :: e !< Height of interfaces [Z ~> m]
315  real, intent(in) :: rho_ref !< A mean density [R ~> kg m-3] or [kg m-3], that is subtracted
316  !! out to reduce the magnitude of each of the integrals.
317  real, intent(in) :: rho_0 !< A density [R ~> kg m-3] or [kg m-3], that is used to calculate
318  !! the pressure (as p~=-z*rho_0*G_e) used in the equation of state.
319  real, intent(in) :: G_e !< The Earth's gravitational acceleration [L2 Z-1 T-2 ~> m s-2]
320  real, intent(in) :: dz_subroundoff !< A minuscule thickness change [Z ~> m]
321  real, dimension(SZI_(HI),SZJ_(HI)), &
322  intent(in) :: bathyT !< The depth of the bathymetry [Z ~> m]
323  type(EOS_type), pointer :: EOS !< Equation of state structure
324  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
325  real, dimension(SZI_(HI),SZJ_(HI)), &
326  intent(inout) :: dpa !< The change in the pressure anomaly across the layer [R L2 T-2 ~> Pa]
327  real, dimension(SZI_(HI),SZJ_(HI)), &
328  optional, intent(inout) :: intz_dpa !< The integral through the thickness of the layer of
329  !! the pressure anomaly relative to the anomaly at the
330  !! top of the layer [R L2 Z T-2 ~> Pa Z]
331  real, dimension(SZIB_(HI),SZJ_(HI)), &
332  optional, intent(inout) :: intx_dpa !< The integral in x of the difference between the
333  !! pressure anomaly at the top and bottom of the layer
334  !! divided by the x grid spacing [R L2 T-2 ~> Pa]
335  real, dimension(SZI_(HI),SZJB_(HI)), &
336  optional, intent(inout) :: inty_dpa !< The integral in y of the difference between the
337  !! pressure anomaly at the top and bottom of the layer
338  !! divided by the y grid spacing [R L2 T-2 ~> Pa]
339  logical, optional, intent(in) :: useMassWghtInterp !< If true, uses mass weighting to
340  !! interpolate T/S for top and bottom integrals.
341 
342 ! This subroutine calculates (by numerical quadrature) integrals of
343 ! pressure anomalies across layers, which are required for calculating the
344 ! finite-volume form pressure accelerations in a Boussinesq model. The one
345 ! potentially dodgy assumption here is that rho_0 is used both in the denominator
346 ! of the accelerations, and in the pressure used to calculated density (the
347 ! latter being -z*rho_0*G_e). These two uses could be separated if need be.
348 !
349 ! It is assumed that the salinity and temperature profiles are linear in the
350 ! vertical. The top and bottom values within each layer are provided and
351 ! a linear interpolation is used to compute intermediate values.
352 
353  ! Local variables
354  real :: T5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Temperatures along a line of subgrid locations [degC]
355  real :: S5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Salinities along a line of subgrid locations [ppt]
356  real :: T25((5*HI%iscB+1):(5*(HI%iecB+2))) ! SGS temperature variance along a line of subgrid locations [degC2]
357  real :: TS5((5*HI%iscB+1):(5*(HI%iecB+2))) ! SGS temp-salt covariance along a line of subgrid locations [degC ppt]
358  real :: S25((5*HI%iscB+1):(5*(HI%iecB+2))) ! SGS salinity variance along a line of subgrid locations [ppt2]
359  real :: p5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Pressures along a line of subgrid locations, never
360  ! rescaled from Pa [Pa]
361  real :: r5((5*HI%iscB+1):(5*(HI%iecB+2))) ! Densities anomalies along a line of subgrid
362  ! locations [R ~> kg m-3] or [kg m-3]
363  real :: T15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Temperatures at an array of subgrid locations [degC]
364  real :: S15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Salinities at an array of subgrid locations [ppt]
365  real :: T215((15*HI%iscB+1):(15*(HI%iecB+1))) ! SGS temperature variance along a line of subgrid locations [degC2]
366  real :: TS15((15*HI%iscB+1):(15*(HI%iecB+1))) ! SGS temp-salt covariance along a line of subgrid locations [degC ppt]
367  real :: S215((15*HI%iscB+1):(15*(HI%iecB+1))) ! SGS salinity variance along a line of subgrid locations [ppt2]
368  real :: p15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Pressures at an array of subgrid locations [Pa]
369  real :: r15((15*HI%iscB+1):(15*(HI%iecB+1))) ! Densities at an array of subgrid locations
370  ! [R ~> kg m-3] or [kg m-3]
371  real :: wt_t(5), wt_b(5) ! Top and bottom weights [nondim]
372  real :: rho_anom ! A density anomaly [R ~> kg m-3] or [kg m-3]
373  real :: w_left, w_right ! Left and right weights [nondim]
374  real :: intz(5) ! The gravitational acceleration times the integrals of density
375  ! with height at the 5 sub-column locations [R L2 T-2 ~> Pa] or [Pa]
376  real, parameter :: C1_90 = 1.0/90.0 ! A rational constant [nondim]
377  real :: GxRho ! The gravitational acceleration times density and unit conversion factors [Pa Z-1 ~> kg m-2 s-2]
378  real :: I_Rho ! The inverse of the Boussinesq density [R-1 ~> m3 kg-1] or [m3 kg-1]
379  real :: rho_scale ! A scaling factor for densities from kg m-3 to R [R m3 kg-1 ~> 1]
380  real :: rho_ref_mks ! The reference density in MKS units, never rescaled from kg m-3 [kg m-3]
381  real :: dz(HI%iscB:HI%iecB+1) ! Layer thicknesses at tracer points [Z ~> m]
382  real :: dz_x(5,HI%iscB:HI%iecB) ! Layer thicknesses along an x-line of subrid locations [Z ~> m]
383  real :: dz_y(5,HI%isc:HI%iec) ! Layer thicknesses along a y-line of subrid locations [Z ~> m]
384  real :: massWeightToggle ! A non-dimensional toggle factor (0 or 1) [nondim]
385  real :: Ttl, Tbl, Ttr, Tbr ! Temperatures at the velocity cell corners [degC]
386  real :: Stl, Sbl, Str, Sbr ! Salinities at the velocity cell corners [ppt]
387  real :: hWght ! A topographically limited thicknes weight [Z ~> m]
388  real :: hL, hR ! Thicknesses to the left and right [Z ~> m]
389  real :: iDenom ! The denominator of the thickness weight expressions [Z-2 ~> m-2]
390  logical :: use_stanley_eos ! True is SGS variance fields exist in tv.
391  logical :: use_varT, use_varS, use_covarTS
392  integer :: Isq, Ieq, Jsq, Jeq, i, j, m, n
393  integer :: pos
394 
395  isq = hi%IscB ; ieq = hi%IecB ; jsq = hi%JscB ; jeq = hi%JecB
396 
397  rho_scale = us%kg_m3_to_R
398  gxrho = us%RL2_T2_to_Pa * g_e * rho_0
399  rho_ref_mks = rho_ref * us%R_to_kg_m3
400  i_rho = 1.0 / rho_0
401  massweighttoggle = 0.
402  if (present(usemasswghtinterp)) then
403  if (usemasswghtinterp) massweighttoggle = 1.
404  endif
405 
406  use_vart = associated(tv%varT)
407  use_covarts = associated(tv%covarTS)
408  use_vars = associated(tv%varS)
409  use_stanley_eos = use_vart .or. use_covarts .or. use_vars
410  t25(:) = 0.
411  ts5(:) = 0.
412  s25(:) = 0.
413  t215(:) = 0.
414  ts15(:) = 0.
415  s215(:) = 0.
416 
417  do n = 1, 5
418  wt_t(n) = 0.25 * real(5-n)
419  wt_b(n) = 1.0 - wt_t(n)
420  enddo
421 
422  ! 1. Compute vertical integrals
423  do j=jsq,jeq+1
424  do i = isq,ieq+1
425  dz(i) = e(i,j,k) - e(i,j,k+1)
426  do n=1,5
427  p5(i*5+n) = -gxrho*(e(i,j,k) - 0.25*real(n-1)*dz(i))
428  ! Salinity and temperature points are linearly interpolated
429  s5(i*5+n) = wt_t(n) * s_t(i,j,k) + wt_b(n) * s_b(i,j,k)
430  t5(i*5+n) = wt_t(n) * t_t(i,j,k) + wt_b(n) * t_b(i,j,k)
431  enddo
432  if (use_vart) t25(i*5+1:i*5+5) = tv%varT(i,j,k)
433  if (use_covarts) ts5(i*5+1:i*5+5) = tv%covarTS(i,j,k)
434  if (use_vars) s25(i*5+1:i*5+5) = tv%varS(i,j,k)
435  enddo
436  if (use_stanley_eos) then
437  if (rho_scale /= 1.0) then
438  call calculate_density(t5, s5, p5, t25, ts5, s25, r5, 1, (ieq-isq+2)*5, eos, &
439  rho_ref=rho_ref_mks, scale=rho_scale)
440  else
441  call calculate_density(t5, s5, p5, t25, ts5, s25, r5, 1, (ieq-isq+2)*5, eos, &
442  rho_ref=rho_ref_mks)
443  endif
444  else
445  if (rho_scale /= 1.0) then
446  call calculate_density(t5, s5, p5, r5, 1, (ieq-isq+2)*5, eos, rho_ref=rho_ref_mks, &
447  scale=rho_scale)
448  else
449  call calculate_density(t5, s5, p5, r5, 1, (ieq-isq+2)*5, eos, rho_ref=rho_ref_mks)
450  endif
451  endif
452 
453  do i=isq,ieq+1
454  ! Use Boole's rule to estimate the pressure anomaly change.
455  rho_anom = c1_90*(7.0*(r5(i*5+1)+r5(i*5+5)) + 32.0*(r5(i*5+2)+r5(i*5+4)) + 12.0*r5(i*5+3))
456  dpa(i,j) = g_e*dz(i)*rho_anom
457  if (present(intz_dpa)) then
458  ! Use a Boole's-rule-like fifth-order accurate estimate of
459  ! the double integral of the pressure anomaly.
460  intz_dpa(i,j) = 0.5*g_e*dz(i)**2 * &
461  (rho_anom - c1_90*(16.0*(r5(i*5+4)-r5(i*5+2)) + 7.0*(r5(i*5+5)-r5(i*5+1))) )
462  endif
463  enddo
464  enddo ! end loops on j
465 
466  ! 2. Compute horizontal integrals in the x direction
467  if (present(intx_dpa)) then ; do j=hi%jsc,hi%jec
468  do i=isq,ieq
469  ! Corner values of T and S
470  ! hWght is the distance measure by which the cell is violation of
471  ! hydrostatic consistency. For large hWght we bias the interpolation
472  ! of T,S along the top and bottom integrals, almost like thickness
473  ! weighting.
474  ! Note: To work in terrain following coordinates we could offset
475  ! this distance by the layer thickness to replicate other models.
476  hwght = massweighttoggle * &
477  max(0., -bathyt(i,j)-e(i+1,j,k), -bathyt(i+1,j)-e(i,j,k))
478  if (hwght > 0.) then
479  hl = (e(i,j,k) - e(i,j,k+1)) + dz_subroundoff
480  hr = (e(i+1,j,k) - e(i+1,j,k+1)) + dz_subroundoff
481  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
482  idenom = 1./( hwght*(hr + hl) + hl*hr )
483  ttl = ( (hwght*hr)*t_t(i+1,j,k) + (hwght*hl + hr*hl)*t_t(i,j,k) ) * idenom
484  ttr = ( (hwght*hl)*t_t(i,j,k) + (hwght*hr + hr*hl)*t_t(i+1,j,k) ) * idenom
485  tbl = ( (hwght*hr)*t_b(i+1,j,k) + (hwght*hl + hr*hl)*t_b(i,j,k) ) * idenom
486  tbr = ( (hwght*hl)*t_b(i,j,k) + (hwght*hr + hr*hl)*t_b(i+1,j,k) ) * idenom
487  stl = ( (hwght*hr)*s_t(i+1,j,k) + (hwght*hl + hr*hl)*s_t(i,j,k) ) * idenom
488  str = ( (hwght*hl)*s_t(i,j,k) + (hwght*hr + hr*hl)*s_t(i+1,j,k) ) * idenom
489  sbl = ( (hwght*hr)*s_b(i+1,j,k) + (hwght*hl + hr*hl)*s_b(i,j,k) ) * idenom
490  sbr = ( (hwght*hl)*s_b(i,j,k) + (hwght*hr + hr*hl)*s_b(i+1,j,k) ) * idenom
491  else
492  ttl = t_t(i,j,k); tbl = t_b(i,j,k); ttr = t_t(i+1,j,k); tbr = t_b(i+1,j,k)
493  stl = s_t(i,j,k); sbl = s_b(i,j,k); str = s_t(i+1,j,k); sbr = s_b(i+1,j,k)
494  endif
495 
496  do m=2,4
497  w_left = wt_t(m) ; w_right = wt_b(m)
498  dz_x(m,i) = w_left*(e(i,j,k) - e(i,j,k+1)) + w_right*(e(i+1,j,k) - e(i+1,j,k+1))
499 
500  ! Salinity and temperature points are linearly interpolated in
501  ! the horizontal. The subscript (1) refers to the top value in
502  ! the vertical profile while subscript (5) refers to the bottom
503  ! value in the vertical profile.
504  pos = i*15+(m-2)*5
505  t15(pos+1) = w_left*ttl + w_right*ttr
506  t15(pos+5) = w_left*tbl + w_right*tbr
507 
508  s15(pos+1) = w_left*stl + w_right*str
509  s15(pos+5) = w_left*sbl + w_right*sbr
510 
511  p15(pos+1) = -gxrho*(w_left*e(i,j,k) + w_right*e(i+1,j,k))
512 
513  ! Pressure
514  do n=2,5
515  p15(pos+n) = p15(pos+n-1) + gxrho*0.25*dz_x(m,i)
516  enddo
517 
518  ! Salinity and temperature (linear interpolation in the vertical)
519  do n=2,4
520  s15(pos+n) = wt_t(n) * s15(pos+1) + wt_b(n) * s15(pos+5)
521  t15(pos+n) = wt_t(n) * t15(pos+1) + wt_b(n) * t15(pos+5)
522  enddo
523  if (use_vart) t215(pos+1:pos+5) = w_left*tv%varT(i,j,k) + w_right*tv%varT(i+1,j,k)
524  if (use_covarts) ts15(pos+1:pos+5) = w_left*tv%covarTS(i,j,k) + w_right*tv%covarTS(i+1,j,k)
525  if (use_vars) s215(pos+1:pos+5) = w_left*tv%varS(i,j,k) + w_right*tv%varS(i+1,j,k)
526  enddo
527  enddo
528 
529  if (use_stanley_eos) then
530  if (rho_scale /= 1.0) then
531  call calculate_density(t15, s15, p15, t215, ts15, s215, r15, 1, 15*(ieq-isq+1), eos, &
532  rho_ref=rho_ref_mks, scale=rho_scale)
533  else
534  call calculate_density(t15, s15, p15, t215, ts15, s215, r15, 1, 15*(ieq-isq+1), eos, &
535  rho_ref=rho_ref_mks)
536  endif
537  else
538  if (rho_scale /= 1.0) then
539  call calculate_density(t15, s15, p15, r15, 1, 15*(ieq-isq+1), eos, rho_ref=rho_ref_mks, &
540  scale=rho_scale)
541  else
542  call calculate_density(t15, s15, p15, r15, 1, 15*(ieq-isq+1), eos, rho_ref=rho_ref_mks)
543  endif
544  endif
545 
546  do i=isq,ieq
547  intz(1) = dpa(i,j) ; intz(5) = dpa(i+1,j)
548 
549  ! Use Boole's rule to estimate the pressure anomaly change.
550  do m = 2,4
551  pos = i*15+(m-2)*5
552  intz(m) = g_e*dz_x(m,i)*( c1_90*(7.0*(r15(pos+1)+r15(pos+5)) + 32.0*(r15(pos+2)+r15(pos+4)) + &
553  12.0*r15(pos+3)))
554  enddo
555  ! Use Boole's rule to integrate the bottom pressure anomaly values in x.
556  intx_dpa(i,j) = c1_90*(7.0*(intz(1)+intz(5)) + 32.0*(intz(2)+intz(4)) + &
557  12.0*intz(3))
558  enddo
559  enddo ; endif
560 
561  ! 3. Compute horizontal integrals in the y direction
562  if (present(inty_dpa)) then ; do j=jsq,jeq
563  do i=hi%isc,hi%iec
564  ! Corner values of T and S
565  ! hWght is the distance measure by which the cell is violation of
566  ! hydrostatic consistency. For large hWght we bias the interpolation
567  ! of T,S along the top and bottom integrals, almost like thickness
568  ! weighting.
569  ! Note: To work in terrain following coordinates we could offset
570  ! this distance by the layer thickness to replicate other models.
571  hwght = massweighttoggle * &
572  max(0., -bathyt(i,j)-e(i,j+1,k), -bathyt(i,j+1)-e(i,j,k))
573  if (hwght > 0.) then
574  hl = (e(i,j,k) - e(i,j,k+1)) + dz_subroundoff
575  hr = (e(i,j+1,k) - e(i,j+1,k+1)) + dz_subroundoff
576  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
577  idenom = 1./( hwght*(hr + hl) + hl*hr )
578  ttl = ( (hwght*hr)*t_t(i,j+1,k) + (hwght*hl + hr*hl)*t_t(i,j,k) ) * idenom
579  ttr = ( (hwght*hl)*t_t(i,j,k) + (hwght*hr + hr*hl)*t_t(i,j+1,k) ) * idenom
580  tbl = ( (hwght*hr)*t_b(i,j+1,k) + (hwght*hl + hr*hl)*t_b(i,j,k) ) * idenom
581  tbr = ( (hwght*hl)*t_b(i,j,k) + (hwght*hr + hr*hl)*t_b(i,j+1,k) ) * idenom
582  stl = ( (hwght*hr)*s_t(i,j+1,k) + (hwght*hl + hr*hl)*s_t(i,j,k) ) * idenom
583  str = ( (hwght*hl)*s_t(i,j,k) + (hwght*hr + hr*hl)*s_t(i,j+1,k) ) * idenom
584  sbl = ( (hwght*hr)*s_b(i,j+1,k) + (hwght*hl + hr*hl)*s_b(i,j,k) ) * idenom
585  sbr = ( (hwght*hl)*s_b(i,j,k) + (hwght*hr + hr*hl)*s_b(i,j+1,k) ) * idenom
586  else
587  ttl = t_t(i,j,k); tbl = t_b(i,j,k); ttr = t_t(i,j+1,k); tbr = t_b(i,j+1,k)
588  stl = s_t(i,j,k); sbl = s_b(i,j,k); str = s_t(i,j+1,k); sbr = s_b(i,j+1,k)
589  endif
590 
591  do m=2,4
592  w_left = wt_t(m) ; w_right = wt_b(m)
593  dz_y(m,i) = w_left*(e(i,j,k) - e(i,j,k+1)) + w_right*(e(i,j+1,k) - e(i,j+1,k+1))
594 
595  ! Salinity and temperature points are linearly interpolated in
596  ! the horizontal. The subscript (1) refers to the top value in
597  ! the vertical profile while subscript (5) refers to the bottom
598  ! value in the vertical profile.
599  pos = i*15+(m-2)*5
600  t15(pos+1) = w_left*ttl + w_right*ttr
601  t15(pos+5) = w_left*tbl + w_right*tbr
602 
603  s15(pos+1) = w_left*stl + w_right*str
604  s15(pos+5) = w_left*sbl + w_right*sbr
605 
606  p15(pos+1) = -gxrho*(w_left*e(i,j,k) + w_right*e(i,j+1,k))
607 
608  ! Pressure
609  do n=2,5
610  p15(pos+n) = p15(pos+n-1) + gxrho*0.25*dz_y(m,i)
611  enddo
612 
613  ! Salinity and temperature (linear interpolation in the vertical)
614  do n=2,4
615  s15(pos+n) = wt_t(n) * s15(pos+1) + wt_b(n) * s15(pos+5)
616  t15(pos+n) = wt_t(n) * t15(pos+1) + wt_b(n) * t15(pos+5)
617  enddo
618  if (use_vart) t215(pos+1:pos+5) = w_left*tv%varT(i,j,k) + w_right*tv%varT(i,j+1,k)
619  if (use_covarts) ts15(pos+1:pos+5) = w_left*tv%covarTS(i,j,k) + w_right*tv%covarTS(i,j+1,k)
620  if (use_vars) s215(pos+1:pos+5) = w_left*tv%varS(i,j,k) + w_right*tv%varS(i,j+1,k)
621  enddo
622  enddo
623 
624  if (use_stanley_eos) then
625  if (rho_scale /= 1.0) then
626  call calculate_density(t15(15*hi%isc+1:), s15(15*hi%isc+1:), p15(15*hi%isc+1:), &
627  t215(15*hi%isc+1:), ts15(15*hi%isc+1:), s215(15*hi%isc+1:), &
628  r15(15*hi%isc+1:), 1, 15*(hi%iec-hi%isc+1), eos, &
629  rho_ref=rho_ref_mks, scale=rho_scale)
630  else
631  call calculate_density(t15(15*hi%isc+1:), s15(15*hi%isc+1:), p15(15*hi%isc+1:), &
632  t215(15*hi%isc+1:), ts15(15*hi%isc+1:), s215(15*hi%isc+1:), &
633  r15(15*hi%isc+1:), 1, 15*(hi%iec-hi%isc+1), eos, rho_ref=rho_ref_mks)
634  endif
635  else
636  if (rho_scale /= 1.0) then
637  call calculate_density(t15(15*hi%isc+1:), s15(15*hi%isc+1:), p15(15*hi%isc+1:), &
638  r15(15*hi%isc+1:), 1, 15*(hi%iec-hi%isc+1), eos, &
639  rho_ref=rho_ref_mks, scale=rho_scale)
640  else
641  call calculate_density(t15(15*hi%isc+1:), s15(15*hi%isc+1:), p15(15*hi%isc+1:), &
642  r15(15*hi%isc+1:), 1, 15*(hi%iec-hi%isc+1), eos, rho_ref=rho_ref_mks)
643  endif
644  endif
645 
646  do i=hi%isc,hi%iec
647  intz(1) = dpa(i,j) ; intz(5) = dpa(i,j+1)
648 
649  ! Use Boole's rule to estimate the pressure anomaly change.
650  do m = 2,4
651  pos = i*15+(m-2)*5
652  intz(m) = g_e*dz_y(m,i)*( c1_90*(7.0*(r15(pos+1)+r15(pos+5)) + &
653  32.0*(r15(pos+2)+r15(pos+4)) + &
654  12.0*r15(pos+3)))
655  enddo
656  ! Use Boole's rule to integrate the values.
657  inty_dpa(i,j) = c1_90*(7.0*(intz(1)+intz(5)) + 32.0*(intz(2)+intz(4)) + &
658  12.0*intz(3))
659  enddo
660  enddo ; endif
661 

◆ int_density_dz_generic_ppm()

subroutine, public mom_density_integrals::int_density_dz_generic_ppm ( integer, intent(in)  k,
type(thermo_var_ptrs), intent(in)  tv,
real, dimension(szi_(hi),szj_(hi),szk_(gv)), intent(in)  T_t,
real, dimension(szi_(hi),szj_(hi),szk_(gv)), intent(in)  T_b,
real, dimension(szi_(hi),szj_(hi),szk_(gv)), intent(in)  S_t,
real, dimension(szi_(hi),szj_(hi),szk_(gv)), intent(in)  S_b,
real, dimension(szi_(hi),szj_(hi),szk_(gv)+1), intent(in)  e,
real, intent(in)  rho_ref,
real, intent(in)  rho_0,
real, intent(in)  G_e,
real, intent(in)  dz_subroundoff,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  bathyT,
type(hor_index_type), intent(in)  HI,
type(verticalgrid_type), intent(in)  GV,
type(eos_type), pointer  EOS,
type(unit_scale_type), intent(in)  US,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(inout)  dpa,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(inout), optional  intz_dpa,
real, dimension( hi %isdb: hi %iedb, hi %jsd: hi %jed), intent(inout), optional  intx_dpa,
real, dimension( hi %isd: hi %ied, hi %jsdb: hi %jedb), intent(inout), optional  inty_dpa,
logical, intent(in), optional  useMassWghtInterp 
)

Compute pressure gradient force integrals for layer "k" and the case where T and S are parabolic profiles.

Parameters
[in]kLayer index to calculate integrals for
[in]hiOcean horizontal index structures for the input arrays
[in]gvVertical grid structure
[in]tvThermodynamic variables
[in]t_tPotential temperature at the cell top [degC]
[in]t_bPotential temperature at the cell bottom [degC]
[in]s_tSalinity at the cell top [ppt]
[in]s_bSalinity at the cell bottom [ppt]
[in]eHeight of interfaces [Z ~> m]
[in]rho_refA mean density [R ~> kg m-3] or [kg m-3], that is subtracted out to reduce the magnitude of each of the integrals.
[in]rho_0A density [R ~> kg m-3] or [kg m-3], that is used to calculate the pressure (as p~=-z*rho_0*G_e) used in the equation of state.
[in]g_eThe Earth's gravitational acceleration [m s-2]
[in]dz_subroundoffA minuscule thickness change [Z ~> m]
[in]bathytThe depth of the bathymetry [Z ~> m]
eosEquation of state structure
[in]usA dimensional unit scaling type
[in,out]dpaThe change in the pressure anomaly across the layer [R L2 T-2 ~> Pa]
[in,out]intz_dpaThe integral through the thickness of the layer of
[in,out]intx_dpaThe integral in x of the difference between the
[in,out]inty_dpaThe integral in y of the difference between the
[in]usemasswghtinterpIf true, uses mass weighting to interpolate T/S for top and bottom integrals.

Definition at line 670 of file MOM_density_integrals.F90.

670  integer, intent(in) :: k !< Layer index to calculate integrals for
671  type(hor_index_type), intent(in) :: HI !< Ocean horizontal index structures for the input arrays
672  type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure
673  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables
674  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), &
675  intent(in) :: T_t !< Potential temperature at the cell top [degC]
676  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), &
677  intent(in) :: T_b !< Potential temperature at the cell bottom [degC]
678  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), &
679  intent(in) :: S_t !< Salinity at the cell top [ppt]
680  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)), &
681  intent(in) :: S_b !< Salinity at the cell bottom [ppt]
682  real, dimension(SZI_(HI),SZJ_(HI),SZK_(GV)+1), &
683  intent(in) :: e !< Height of interfaces [Z ~> m]
684  real, intent(in) :: rho_ref !< A mean density [R ~> kg m-3] or [kg m-3], that is
685  !! subtracted out to reduce the magnitude of each of the integrals.
686  real, intent(in) :: rho_0 !< A density [R ~> kg m-3] or [kg m-3], that is used to calculate
687  !! the pressure (as p~=-z*rho_0*G_e) used in the equation of state.
688  real, intent(in) :: G_e !< The Earth's gravitational acceleration [m s-2]
689  real, intent(in) :: dz_subroundoff !< A minuscule thickness change [Z ~> m]
690  real, dimension(SZI_(HI),SZJ_(HI)), &
691  intent(in) :: bathyT !< The depth of the bathymetry [Z ~> m]
692  type(EOS_type), pointer :: EOS !< Equation of state structure
693  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
694  real, dimension(SZI_(HI),SZJ_(HI)), &
695  intent(inout) :: dpa !< The change in the pressure anomaly across the layer [R L2 T-2 ~> Pa]
696  real, dimension(SZI_(HI),SZJ_(HI)), &
697  optional, intent(inout) :: intz_dpa !< The integral through the thickness of the layer of
698  !! the pressure anomaly relative to the anomaly at the
699  !! top of the layer [R L2 Z T-2 ~> Pa m]
700  real, dimension(SZIB_(HI),SZJ_(HI)), &
701  optional, intent(inout) :: intx_dpa !< The integral in x of the difference between the
702  !! pressure anomaly at the top and bottom of the layer
703  !! divided by the x grid spacing [R L2 T-2 ~> Pa]
704  real, dimension(SZI_(HI),SZJB_(HI)), &
705  optional, intent(inout) :: inty_dpa !< The integral in y of the difference between the
706  !! pressure anomaly at the top and bottom of the layer
707  !! divided by the y grid spacing [R L2 T-2 ~> Pa]
708  logical, optional, intent(in) :: useMassWghtInterp !< If true, uses mass weighting to
709  !! interpolate T/S for top and bottom integrals.
710 
711 ! This subroutine calculates (by numerical quadrature) integrals of
712 ! pressure anomalies across layers, which are required for calculating the
713 ! finite-volume form pressure accelerations in a Boussinesq model. The one
714 ! potentially dodgy assumption here is that rho_0 is used both in the denominator
715 ! of the accelerations, and in the pressure used to calculated density (the
716 ! latter being -z*rho_0*G_e). These two uses could be separated if need be.
717 !
718 ! It is assumed that the salinity and temperature profiles are parabolic in the
719 ! vertical. The top and bottom values within each layer are provided and
720 ! a parabolic interpolation is used to compute intermediate values.
721 
722  ! Local variables
723  real :: T5(5) ! Temperatures along a line of subgrid locations [degC]
724  real :: S5(5) ! Salinities along a line of subgrid locations [ppt]
725  real :: T25(5) ! SGS temperature variance along a line of subgrid locations [degC2]
726  real :: TS5(5) ! SGS temperature-salinity covariance along a line of subgrid locations [degC ppt]
727  real :: S25(5) ! SGS salinity variance along a line of subgrid locations [ppt2]
728  real :: p5(5) ! Pressures at five quadrature points, never rescaled from Pa [Pa]
729  real :: r5(5) ! Density anomalies from rho_ref at quadrature points [R ~> kg m-3] or [kg m-3]
730  real :: wt_t(5), wt_b(5) ! Top and bottom weights [nondim]
731  real :: rho_anom ! The integrated density anomaly [R ~> kg m-3] or [kg m-3]
732  real :: w_left, w_right ! Left and right weights [nondim]
733  real :: intz(5) ! The gravitational acceleration times the integrals of density
734  ! with height at the 5 sub-column locations [R L2 T-2 ~> Pa] or [Pa]
735  real, parameter :: C1_90 = 1.0/90.0 ! Rational constants.
736  real :: GxRho ! The gravitational acceleration times density and unit conversion factors [Pa Z-1 ~> kg m-2 s-2]
737  real :: I_Rho ! The inverse of the Boussinesq density [R-1 ~> m3 kg-1] or [m3 kg-1]
738  real :: rho_scale ! A scaling factor for densities from kg m-3 to R [R m3 kg-1 ~> 1]
739  real :: rho_ref_mks ! The reference density in MKS units, never rescaled from kg m-3 [kg m-3]
740  real :: dz ! Layer thicknesses at tracer points [Z ~> m]
741  real :: massWeightToggle ! A non-dimensional toggle factor (0 or 1) [nondim]
742  real :: Ttl, Tbl, Tml, Ttr, Tbr, Tmr ! Temperatures at the velocity cell corners [degC]
743  real :: Stl, Sbl, Sml, Str, Sbr, Smr ! Salinities at the velocity cell corners [ppt]
744  real :: s6 ! PPM curvature coefficient for S [ppt]
745  real :: t6 ! PPM curvature coefficient for T [degC]
746  real :: T_top, T_mn, T_bot ! Left edge, cell mean and right edge values used in PPM reconstructions of T
747  real :: S_top, S_mn, S_bot ! Left edge, cell mean and right edge values used in PPM reconstructions of S
748  real :: hWght ! A topographically limited thicknes weight [Z ~> m]
749  real :: hL, hR ! Thicknesses to the left and right [Z ~> m]
750  real :: iDenom ! The denominator of the thickness weight expressions [Z-2 ~> m-2]
751  integer :: Isq, Ieq, Jsq, Jeq, i, j, m, n
752  logical :: use_PPM ! If false, assume zero curvature in reconstruction, i.e. PLM
753  logical :: use_stanley_eos ! True is SGS variance fields exist in tv.
754  logical :: use_varT, use_varS, use_covarTS
755 
756  isq = hi%IscB ; ieq = hi%IecB ; jsq = hi%JscB ; jeq = hi%JecB
757 
758  rho_scale = us%kg_m3_to_R
759  gxrho = us%RL2_T2_to_Pa * g_e * rho_0
760  rho_ref_mks = rho_ref * us%R_to_kg_m3
761  i_rho = 1.0 / rho_0
762  massweighttoggle = 0.
763  if (present(usemasswghtinterp)) then
764  if (usemasswghtinterp) massweighttoggle = 1.
765  endif
766 
767  ! In event PPM calculation is bypassed with use_PPM=False
768  s6 = 0.
769  t6 = 0.
770  use_ppm = .true. ! This is a place-holder to allow later re-use of this function
771 
772  use_vart = associated(tv%varT)
773  use_covarts = associated(tv%covarTS)
774  use_vars = associated(tv%varS)
775  use_stanley_eos = use_vart .or. use_covarts .or. use_vars
776  t25(:) = 0.
777  ts5(:) = 0.
778  s25(:) = 0.
779 
780  do n = 1, 5
781  wt_t(n) = 0.25 * real(5-n)
782  wt_b(n) = 1.0 - wt_t(n)
783  enddo
784 
785  ! 1. Compute vertical integrals
786  do j=jsq,jeq+1 ; do i=isq,ieq+1
787  if (use_ppm) then
788  ! Curvature coefficient of the parabolas
789  s6 = 3.0 * ( 2.0*tv%S(i,j,k) - ( s_t(i,j,k) + s_b(i,j,k) ) )
790  t6 = 3.0 * ( 2.0*tv%T(i,j,k) - ( t_t(i,j,k) + t_b(i,j,k) ) )
791  endif
792  dz = e(i,j,k) - e(i,j,k+1)
793  do n=1,5
794  p5(n) = -gxrho*(e(i,j,k) - 0.25*real(n-1)*dz)
795  ! Salinity and temperature points are reconstructed with PPM
796  s5(n) = wt_t(n) * s_t(i,j,k) + wt_b(n) * ( s_b(i,j,k) + s6 * wt_t(n) )
797  t5(n) = wt_t(n) * t_t(i,j,k) + wt_b(n) * ( t_b(i,j,k) + t6 * wt_t(n) )
798  enddo
799  if (use_stanley_eos) then
800  if (use_vart) t25(:) = tv%varT(i,j,k)
801  if (use_covarts) ts5(:) = tv%covarTS(i,j,k)
802  if (use_vars) s25(:) = tv%varS(i,j,k)
803  call calculate_density(t5, s5, p5, t25, ts5, s25, r5, &
804  1, 5, eos, rho_ref=rho_ref_mks, scale=rho_scale)
805  else
806  call calculate_density(t5, s5, p5, r5, 1, 5, eos, rho_ref=rho_ref_mks, scale=rho_scale)
807  endif
808 
809  ! Use Boole's rule to estimate the pressure anomaly change.
810  rho_anom = c1_90*(7.0*(r5(1)+r5(5)) + 32.0*(r5(2)+r5(4)) + 12.0*r5(3))
811  dpa(i,j) = g_e*dz*rho_anom
812  if (present(intz_dpa)) then
813  ! Use a Boole's-rule-like fifth-order accurate estimate of
814  ! the double integral of the pressure anomaly.
815  intz_dpa(i,j) = 0.5*g_e*dz**2 * &
816  (rho_anom - c1_90*(16.0*(r5(4)-r5(2)) + 7.0*(r5(5)-r5(1))) )
817  endif
818  enddo ; enddo ! end loops on j and i
819 
820  ! 2. Compute horizontal integrals in the x direction
821  if (present(intx_dpa)) then ; do j=hi%jsc,hi%jec ; do i=isq,ieq
822  ! Corner values of T and S
823  ! hWght is the distance measure by which the cell is violation of
824  ! hydrostatic consistency. For large hWght we bias the interpolation
825  ! of T,S along the top and bottom integrals, almost like thickness
826  ! weighting.
827  ! Note: To work in terrain following coordinates we could offset
828  ! this distance by the layer thickness to replicate other models.
829  hwght = massweighttoggle * &
830  max(0., -bathyt(i,j)-e(i+1,j,k), -bathyt(i+1,j)-e(i,j,k))
831  if (hwght > 0.) then
832  hl = (e(i,j,k) - e(i,j,k+1)) + dz_subroundoff
833  hr = (e(i+1,j,k) - e(i+1,j,k+1)) + dz_subroundoff
834  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
835  idenom = 1./( hwght*(hr + hl) + hl*hr )
836  ttl = ( (hwght*hr)*t_t(i+1,j,k) + (hwght*hl + hr*hl)*t_t(i,j,k) ) * idenom
837  tbl = ( (hwght*hr)*t_b(i+1,j,k) + (hwght*hl + hr*hl)*t_b(i,j,k) ) * idenom
838  tml = ( (hwght*hr)*tv%T(i+1,j,k)+ (hwght*hl + hr*hl)*tv%T(i,j,k) ) * idenom
839  ttr = ( (hwght*hl)*t_t(i,j,k) + (hwght*hr + hr*hl)*t_t(i+1,j,k) ) * idenom
840  tbr = ( (hwght*hl)*t_b(i,j,k) + (hwght*hr + hr*hl)*t_b(i+1,j,k) ) * idenom
841  tmr = ( (hwght*hl)*tv%T(i,j,k) + (hwght*hr + hr*hl)*tv%T(i+1,j,k) ) * idenom
842  stl = ( (hwght*hr)*s_t(i+1,j,k) + (hwght*hl + hr*hl)*s_t(i,j,k) ) * idenom
843  sbl = ( (hwght*hr)*s_b(i+1,j,k) + (hwght*hl + hr*hl)*s_b(i,j,k) ) * idenom
844  sml = ( (hwght*hr)*tv%S(i+1,j,k) + (hwght*hl + hr*hl)*tv%S(i,j,k) ) * idenom
845  str = ( (hwght*hl)*s_t(i,j,k) + (hwght*hr + hr*hl)*s_t(i+1,j,k) ) * idenom
846  sbr = ( (hwght*hl)*s_b(i,j,k) + (hwght*hr + hr*hl)*s_b(i+1,j,k) ) * idenom
847  smr = ( (hwght*hl)*tv%S(i,j,k) + (hwght*hr + hr*hl)*tv%S(i+1,j,k) ) * idenom
848  else
849  ttl = t_t(i,j,k); tbl = t_b(i,j,k); ttr = t_t(i+1,j,k); tbr = t_b(i+1,j,k)
850  tml = tv%T(i,j,k); tmr = tv%T(i+1,j,k)
851  stl = s_t(i,j,k); sbl = s_b(i,j,k); str = s_t(i+1,j,k); sbr = s_b(i+1,j,k)
852  sml = tv%S(i,j,k); smr = tv%S(i+1,j,k)
853  endif
854 
855  do m=2,4
856  w_left = wt_t(m) ; w_right = wt_b(m)
857 
858  ! Salinity and temperature points are linearly interpolated in
859  ! the horizontal. The subscript (1) refers to the top value in
860  ! the vertical profile while subscript (5) refers to the bottom
861  ! value in the vertical profile.
862  t_top = w_left*ttl + w_right*ttr
863  t_mn = w_left*tml + w_right*tmr
864  t_bot = w_left*tbl + w_right*tbr
865 
866  s_top = w_left*stl + w_right*str
867  s_mn = w_left*sml + w_right*smr
868  s_bot = w_left*sbl + w_right*sbr
869 
870  ! Pressure
871  dz = w_left*(e(i,j,k) - e(i,j,k+1)) + w_right*(e(i+1,j,k) - e(i+1,j,k+1))
872  p5(1) = -gxrho*(w_left*e(i,j,k) + w_right*e(i+1,j,k))
873  do n=2,5
874  p5(n) = p5(n-1) + gxrho*0.25*dz
875  enddo
876 
877  ! Parabolic reconstructions in the vertical for T and S
878  if (use_ppm) then
879  ! Coefficients of the parabolas
880  s6 = 3.0 * ( 2.0*s_mn - ( s_top + s_bot ) )
881  t6 = 3.0 * ( 2.0*t_mn - ( t_top + t_bot ) )
882  endif
883  do n=1,5
884  s5(n) = wt_t(n) * s_top + wt_b(n) * ( s_bot + s6 * wt_t(n) )
885  t5(n) = wt_t(n) * t_top + wt_b(n) * ( t_bot + t6 * wt_t(n) )
886  enddo
887 
888  if (use_stanley_eos) then
889  if (use_vart) t25(:) = w_left*tv%varT(i,j,k) + w_right*tv%varT(i+1,j,k)
890  if (use_covarts) ts5(:) = w_left*tv%covarTS(i,j,k) + w_right*tv%covarTS(i+1,j,k)
891  if (use_vars) s25(:) = w_left*tv%varS(i,j,k) + w_right*tv%varS(i+1,j,k)
892  call calculate_density(t5, s5, p5, t25, ts5, s25, r5, &
893  1, 5, eos, rho_ref=rho_ref_mks, scale=rho_scale)
894  else
895  call calculate_density(t5, s5, p5, r5, 1, 5, eos, rho_ref=rho_ref_mks, scale=rho_scale)
896  endif
897 
898  ! Use Boole's rule to estimate the pressure anomaly change.
899  intz(m) = g_e*dz*( c1_90*(7.0*(r5(1)+r5(5)) + 32.0*(r5(2)+r5(4)) + 12.0*r5(3)) )
900  enddo ! m
901  intz(1) = dpa(i,j) ; intz(5) = dpa(i+1,j)
902 
903  ! Use Boole's rule to integrate the bottom pressure anomaly values in x.
904  intx_dpa(i,j) = c1_90*(7.0*(intz(1)+intz(5)) + 32.0*(intz(2)+intz(4)) + 12.0*intz(3))
905 
906  enddo ; enddo ; endif
907 
908  ! 3. Compute horizontal integrals in the y direction
909  if (present(inty_dpa)) then ; do j=jsq,jeq ; do i=hi%isc,hi%iec
910  ! Corner values of T and S
911  ! hWght is the distance measure by which the cell is violation of
912  ! hydrostatic consistency. For large hWght we bias the interpolation
913  ! of T,S along the top and bottom integrals, almost like thickness
914  ! weighting.
915  ! Note: To work in terrain following coordinates we could offset
916  ! this distance by the layer thickness to replicate other models.
917  hwght = massweighttoggle * &
918  max(0., -bathyt(i,j)-e(i,j+1,k), -bathyt(i,j+1)-e(i,j,k))
919  if (hwght > 0.) then
920  hl = (e(i,j,k) - e(i,j,k+1)) + dz_subroundoff
921  hr = (e(i,j+1,k) - e(i,j+1,k+1)) + dz_subroundoff
922  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
923  idenom = 1./( hwght*(hr + hl) + hl*hr )
924  ttl = ( (hwght*hr)*t_t(i,j+1,k) + (hwght*hl + hr*hl)*t_t(i,j,k) ) * idenom
925  tbl = ( (hwght*hr)*t_b(i,j+1,k) + (hwght*hl + hr*hl)*t_b(i,j,k) ) * idenom
926  tml = ( (hwght*hr)*tv%T(i,j+1,k)+ (hwght*hl + hr*hl)*tv%T(i,j,k) ) * idenom
927  ttr = ( (hwght*hl)*t_t(i,j,k) + (hwght*hr + hr*hl)*t_t(i,j+1,k) ) * idenom
928  tbr = ( (hwght*hl)*t_b(i,j,k) + (hwght*hr + hr*hl)*t_b(i,j+1,k) ) * idenom
929  tmr = ( (hwght*hl)*tv%T(i,j,k) + (hwght*hr + hr*hl)*tv%T(i,j+1,k) ) * idenom
930  stl = ( (hwght*hr)*s_t(i,j+1,k) + (hwght*hl + hr*hl)*s_t(i,j,k) ) * idenom
931  sbl = ( (hwght*hr)*s_b(i,j+1,k) + (hwght*hl + hr*hl)*s_b(i,j,k) ) * idenom
932  sml = ( (hwght*hr)*tv%S(i,j+1,k)+ (hwght*hl + hr*hl)*tv%S(i,j,k) ) * idenom
933  str = ( (hwght*hl)*s_t(i,j,k) + (hwght*hr + hr*hl)*s_t(i,j+1,k) ) * idenom
934  sbr = ( (hwght*hl)*s_b(i,j,k) + (hwght*hr + hr*hl)*s_b(i,j+1,k) ) * idenom
935  smr = ( (hwght*hl)*tv%S(i,j,k) + (hwght*hr + hr*hl)*tv%S(i,j+1,k) ) * idenom
936  else
937  ttl = t_t(i,j,k); tbl = t_b(i,j,k); ttr = t_t(i,j+1,k); tbr = t_b(i,j+1,k)
938  tml = tv%T(i,j,k); tmr = tv%T(i,j+1,k)
939  stl = s_t(i,j,k); sbl = s_b(i,j,k); str = s_t(i,j+1,k); sbr = s_b(i,j+1,k)
940  sml = tv%S(i,j,k); smr = tv%S(i,j+1,k)
941  endif
942 
943  do m=2,4
944  w_left = wt_t(m) ; w_right = wt_b(m)
945 
946  ! Salinity and temperature points are linearly interpolated in
947  ! the horizontal. The subscript (1) refers to the top value in
948  ! the vertical profile while subscript (5) refers to the bottom
949  ! value in the vertical profile.
950  t_top = w_left*ttl + w_right*ttr
951  t_mn = w_left*tml + w_right*tmr
952  t_bot = w_left*tbl + w_right*tbr
953 
954  s_top = w_left*stl + w_right*str
955  s_mn = w_left*sml + w_right*smr
956  s_bot = w_left*sbl + w_right*sbr
957 
958  ! Pressure
959  dz = w_left*(e(i,j,k) - e(i,j,k+1)) + w_right*(e(i,j+1,k) - e(i,j+1,k+1))
960  p5(1) = -gxrho*(w_left*e(i,j,k) + w_right*e(i,j+1,k))
961  do n=2,5
962  p5(n) = p5(n-1) + gxrho*0.25*dz
963  enddo
964 
965  ! Parabolic reconstructions in the vertical for T and S
966  if (use_ppm) then
967  ! Coefficients of the parabolas
968  s6 = 3.0 * ( 2.0*s_mn - ( s_top + s_bot ) )
969  t6 = 3.0 * ( 2.0*t_mn - ( t_top + t_bot ) )
970  endif
971  do n=1,5
972  s5(n) = wt_t(n) * s_top + wt_b(n) * ( s_bot + s6 * wt_t(n) )
973  t5(n) = wt_t(n) * t_top + wt_b(n) * ( t_bot + t6 * wt_t(n) )
974  enddo
975 
976  if (use_stanley_eos) then
977  if (use_vart) t25(:) = w_left*tv%varT(i,j,k) + w_right*tv%varT(i,j+1,k)
978  if (use_covarts) ts5(:) = w_left*tv%covarTS(i,j,k) + w_right*tv%covarTS(i,j+1,k)
979  if (use_vars) s25(:) = w_left*tv%varS(i,j,k) + w_right*tv%varS(i,j+1,k)
980  call calculate_density(t5, s5, p5, t25, ts5, s25, r5, &
981  1, 5, eos, rho_ref=rho_ref_mks, scale=rho_scale)
982  else
983  call calculate_density(t5, s5, p5, r5, 1, 5, eos, rho_ref=rho_ref_mks, scale=rho_scale)
984  endif
985 
986  ! Use Boole's rule to estimate the pressure anomaly change.
987  intz(m) = g_e*dz*( c1_90*(7.0*(r5(1)+r5(5)) + 32.0*(r5(2)+r5(4)) + 12.0*r5(3)) )
988  enddo ! m
989  intz(1) = dpa(i,j) ; intz(5) = dpa(i,j+1)
990 
991  ! Use Boole's rule to integrate the bottom pressure anomaly values in y.
992  inty_dpa(i,j) = c1_90*(7.0*(intz(1)+intz(5)) + 32.0*(intz(2)+intz(4)) + 12.0*intz(3))
993 
994  enddo ; enddo ; endif
995 

◆ int_spec_vol_dp_generic_pcm()

subroutine, public mom_density_integrals::int_spec_vol_dp_generic_pcm ( real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  T,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  S,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  p_t,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  p_b,
real, intent(in)  alpha_ref,
type(hor_index_type), intent(in)  HI,
type(eos_type), pointer  EOS,
type(unit_scale_type), intent(in)  US,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(inout)  dza,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(inout), optional  intp_dza,
real, dimension( hi %isdb: hi %iedb, hi %jsd: hi %jed), intent(inout), optional  intx_dza,
real, dimension( hi %isd: hi %ied, hi %jsdb: hi %jedb), intent(inout), optional  inty_dza,
integer, intent(in), optional  halo_size,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in), optional  bathyP,
real, intent(in), optional  dP_neglect,
logical, intent(in), optional  useMassWghtInterp 
)

This subroutine calculates integrals of specific volume anomalies in pressure across layers, which are required for calculating the finite-volume form pressure accelerations in a non-Boussinesq model. There are essentially no free assumptions, apart from the use of Boole's rule quadrature to do the integrals.

Parameters
[in]hiA horizontal index type structure.
[in]tPotential temperature of the layer [degC]
[in]sSalinity of the layer [ppt]
[in]p_tPressure atop the layer [R L2 T-2 ~> Pa] or [Pa]
[in]p_bPressure below the layer [R L2 T-2 ~> Pa] or [Pa]
[in]alpha_refA mean specific volume that is subtracted out to reduce the magnitude of each of the integrals [R-1 ~> m3 kg-1] The calculation is mathematically identical with different values of alpha_ref, but alpha_ref alters the effects of roundoff, and answers do change.
eosEquation of state structure
[in]usA dimensional unit scaling type
[in,out]dzaThe change in the geopotential anomaly
[in,out]intp_dzaThe integral in pressure through the layer of
[in,out]intx_dzaThe integral in x of the difference between
[in,out]inty_dzaThe integral in y of the difference between
[in]halo_sizeThe width of halo points on which to calculate dza.
[in]bathypThe pressure at the bathymetry [R L2 T-2 ~> Pa] or [Pa]
[in]dp_neglectA minuscule pressure change with the same units as p_t [R L2 T-2 ~> Pa] or [Pa]
[in]usemasswghtinterpIf true, uses mass weighting to interpolate T/S for top and bottom integrals.

Definition at line 1065 of file MOM_density_integrals.F90.

1065  type(hor_index_type), intent(in) :: HI !< A horizontal index type structure.
1066  real, dimension(SZI_(HI),SZJ_(HI)), &
1067  intent(in) :: T !< Potential temperature of the layer [degC]
1068  real, dimension(SZI_(HI),SZJ_(HI)), &
1069  intent(in) :: S !< Salinity of the layer [ppt]
1070  real, dimension(SZI_(HI),SZJ_(HI)), &
1071  intent(in) :: p_t !< Pressure atop the layer [R L2 T-2 ~> Pa] or [Pa]
1072  real, dimension(SZI_(HI),SZJ_(HI)), &
1073  intent(in) :: p_b !< Pressure below the layer [R L2 T-2 ~> Pa] or [Pa]
1074  real, intent(in) :: alpha_ref !< A mean specific volume that is subtracted out
1075  !! to reduce the magnitude of each of the integrals [R-1 ~> m3 kg-1]
1076  !! The calculation is mathematically identical with different values of
1077  !! alpha_ref, but alpha_ref alters the effects of roundoff, and
1078  !! answers do change.
1079  type(EOS_type), pointer :: EOS !< Equation of state structure
1080  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
1081  real, dimension(SZI_(HI),SZJ_(HI)), &
1082  intent(inout) :: dza !< The change in the geopotential anomaly
1083  !! across the layer [L2 T-2 ~> m2 s-2] or [m2 s-2]
1084  real, dimension(SZI_(HI),SZJ_(HI)), &
1085  optional, intent(inout) :: intp_dza !< The integral in pressure through the layer of
1086  !! the geopotential anomaly relative to the anomaly at the bottom of the
1087  !! layer [R L4 T-4 ~> Pa m2 s-2] or [Pa m2 s-2]
1088  real, dimension(SZIB_(HI),SZJ_(HI)), &
1089  optional, intent(inout) :: intx_dza !< The integral in x of the difference between
1090  !! the geopotential anomaly at the top and bottom of the layer divided
1091  !! by the x grid spacing [L2 T-2 ~> m2 s-2] or [m2 s-2]
1092  real, dimension(SZI_(HI),SZJB_(HI)), &
1093  optional, intent(inout) :: inty_dza !< The integral in y of the difference between
1094  !! the geopotential anomaly at the top and bottom of the layer divided
1095  !! by the y grid spacing [L2 T-2 ~> m2 s-2] or [m2 s-2]
1096  integer, optional, intent(in) :: halo_size !< The width of halo points on which to calculate dza.
1097  real, dimension(SZI_(HI),SZJ_(HI)), &
1098  optional, intent(in) :: bathyP !< The pressure at the bathymetry [R L2 T-2 ~> Pa] or [Pa]
1099  real, optional, intent(in) :: dP_neglect !< A minuscule pressure change with
1100  !! the same units as p_t [R L2 T-2 ~> Pa] or [Pa]
1101  logical, optional, intent(in) :: useMassWghtInterp !< If true, uses mass weighting
1102  !! to interpolate T/S for top and bottom integrals.
1103 
1104 ! This subroutine calculates analytical and nearly-analytical integrals in
1105 ! pressure across layers of geopotential anomalies, which are required for
1106 ! calculating the finite-volume form pressure accelerations in a non-Boussinesq
1107 ! model. There are essentially no free assumptions, apart from the use of
1108 ! Boole's rule to do the horizontal integrals, and from a truncation in the
1109 ! series for log(1-eps/1+eps) that assumes that |eps| < 0.34.
1110 
1111  ! Local variables
1112  real :: T5(5) ! Temperatures at five quadrature points [degC]
1113  real :: S5(5) ! Salinities at five quadrature points [ppt]
1114  real :: p5(5) ! Pressures at five quadrature points, scaled back to Pa if necessary [Pa]
1115  real :: a5(5) ! Specific volumes at five quadrature points [R-1 ~> m3 kg-1] or [m3 kg-1]
1116  real :: alpha_anom ! The depth averaged specific density anomaly [R-1 ~> m3 kg-1]
1117  real :: dp ! The pressure change through a layer [R L2 T-2 ~> Pa]
1118  real :: hWght ! A pressure-thickness below topography [R L2 T-2 ~> Pa]
1119  real :: hL, hR ! Pressure-thicknesses of the columns to the left and right [R L2 T-2 ~> Pa]
1120  real :: alpha_ref_mks ! The reference specific volume in MKS units, never rescaled from m3 kg-1 [m3 kg-1]
1121  real :: iDenom ! The inverse of the denominator in the weights [T4 R-2 L-4 ~> Pa-2]
1122  real :: hWt_LL, hWt_LR ! hWt_LA is the weighted influence of A on the left column [nondim]
1123  real :: hWt_RL, hWt_RR ! hWt_RA is the weighted influence of A on the right column [nondim]
1124  real :: wt_L, wt_R ! The linear weights of the left and right columns [nondim]
1125  real :: wtT_L, wtT_R ! The weights for tracers from the left and right columns [nondim]
1126  real :: intp(5) ! The integrals of specific volume with pressure at the
1127  ! 5 sub-column locations [L2 T-2 ~> m2 s-2]
1128  real :: RL2_T2_to_Pa ! A unit conversion factor from the rescaled units of pressure to Pa [Pa T2 R-1 L-2 ~> 1]
1129  real :: SV_scale ! A multiplicative factor by which to scale specific
1130  ! volume from m3 kg-1 to the desired units [kg m-3 R-1 ~> 1]
1131  logical :: do_massWeight ! Indicates whether to do mass weighting.
1132  real, parameter :: C1_90 = 1.0/90.0 ! A rational constant.
1133  integer :: Isq, Ieq, Jsq, Jeq, ish, ieh, jsh, jeh, i, j, m, n, halo
1134 
1135  isq = hi%IscB ; ieq = hi%IecB ; jsq = hi%JscB ; jeq = hi%JecB
1136  halo = 0 ; if (present(halo_size)) halo = max(halo_size,0)
1137  ish = hi%isc-halo ; ieh = hi%iec+halo ; jsh = hi%jsc-halo ; jeh = hi%jec+halo
1138  if (present(intx_dza)) then ; ish = min(isq,ish) ; ieh = max(ieq+1,ieh); endif
1139  if (present(inty_dza)) then ; jsh = min(jsq,jsh) ; jeh = max(jeq+1,jeh); endif
1140 
1141  sv_scale = us%R_to_kg_m3
1142  rl2_t2_to_pa = us%RL2_T2_to_Pa
1143  alpha_ref_mks = alpha_ref * us%kg_m3_to_R
1144 
1145  do_massweight = .false.
1146  if (present(usemasswghtinterp)) then ; if (usemasswghtinterp) then
1147  do_massweight = .true.
1148  if (.not.present(bathyp)) call mom_error(fatal, "int_spec_vol_dp_generic: "//&
1149  "bathyP must be present if useMassWghtInterp is present and true.")
1150  if (.not.present(dp_neglect)) call mom_error(fatal, "int_spec_vol_dp_generic: "//&
1151  "dP_neglect must be present if useMassWghtInterp is present and true.")
1152  endif ; endif
1153 
1154  do j=jsh,jeh ; do i=ish,ieh
1155  dp = p_b(i,j) - p_t(i,j)
1156  do n=1,5
1157  t5(n) = t(i,j) ; s5(n) = s(i,j)
1158  p5(n) = rl2_t2_to_pa * (p_b(i,j) - 0.25*real(n-1)*dp)
1159  enddo
1160 
1161  if (sv_scale /= 1.0) then
1162  call calculate_spec_vol(t5, s5, p5, a5, 1, 5, eos, alpha_ref_mks, scale=sv_scale)
1163  else
1164  call calculate_spec_vol(t5, s5, p5, a5, 1, 5, eos, alpha_ref_mks)
1165  endif
1166 
1167  ! Use Boole's rule to estimate the interface height anomaly change.
1168  alpha_anom = c1_90*(7.0*(a5(1)+a5(5)) + 32.0*(a5(2)+a5(4)) + 12.0*a5(3))
1169  dza(i,j) = dp*alpha_anom
1170  ! Use a Boole's-rule-like fifth-order accurate estimate of the double integral of
1171  ! the interface height anomaly.
1172  if (present(intp_dza)) intp_dza(i,j) = 0.5*dp**2 * &
1173  (alpha_anom - c1_90*(16.0*(a5(4)-a5(2)) + 7.0*(a5(5)-a5(1))) )
1174  enddo ; enddo
1175 
1176  if (present(intx_dza)) then ; do j=hi%jsc,hi%jec ; do i=isq,ieq
1177  ! hWght is the distance measure by which the cell is violation of
1178  ! hydrostatic consistency. For large hWght we bias the interpolation of
1179  ! T & S along the top and bottom integrals, akin to thickness weighting.
1180  hwght = 0.0
1181  if (do_massweight) &
1182  hwght = max(0., bathyp(i,j)-p_t(i+1,j), bathyp(i+1,j)-p_t(i,j))
1183  if (hwght > 0.) then
1184  hl = (p_b(i,j) - p_t(i,j)) + dp_neglect
1185  hr = (p_b(i+1,j) - p_t(i+1,j)) + dp_neglect
1186  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
1187  idenom = 1.0 / ( hwght*(hr + hl) + hl*hr )
1188  hwt_ll = (hwght*hl + hr*hl) * idenom ; hwt_lr = (hwght*hr) * idenom
1189  hwt_rr = (hwght*hr + hr*hl) * idenom ; hwt_rl = (hwght*hl) * idenom
1190  else
1191  hwt_ll = 1.0 ; hwt_lr = 0.0 ; hwt_rr = 1.0 ; hwt_rl = 0.0
1192  endif
1193 
1194  intp(1) = dza(i,j) ; intp(5) = dza(i+1,j)
1195  do m=2,4
1196  wt_l = 0.25*real(5-m) ; wt_r = 1.0-wt_l
1197  wtt_l = wt_l*hwt_ll + wt_r*hwt_rl ; wtt_r = wt_l*hwt_lr + wt_r*hwt_rr
1198 
1199  ! T, S, and p are interpolated in the horizontal. The p interpolation
1200  ! is linear, but for T and S it may be thickness weighted.
1201  p5(1) = rl2_t2_to_pa * (wt_l*p_b(i,j) + wt_r*p_b(i+1,j))
1202  dp = wt_l*(p_b(i,j) - p_t(i,j)) + wt_r*(p_b(i+1,j) - p_t(i+1,j))
1203  t5(1) = wtt_l*t(i,j) + wtt_r*t(i+1,j)
1204  s5(1) = wtt_l*s(i,j) + wtt_r*s(i+1,j)
1205 
1206  do n=2,5
1207  t5(n) = t5(1) ; s5(n) = s5(1) ; p5(n) = p5(n-1) - rl2_t2_to_pa * 0.25*dp
1208  enddo
1209  if (sv_scale /= 1.0) then
1210  call calculate_spec_vol(t5, s5, p5, a5, 1, 5, eos, alpha_ref_mks, scale=sv_scale)
1211  else
1212  call calculate_spec_vol(t5, s5, p5, a5, 1, 5, eos, alpha_ref_mks)
1213  endif
1214 
1215  ! Use Boole's rule to estimate the interface height anomaly change.
1216  intp(m) = dp*( c1_90*(7.0*(a5(1)+a5(5)) + 32.0*(a5(2)+a5(4)) + &
1217  12.0*a5(3)))
1218  enddo
1219  ! Use Boole's rule to integrate the interface height anomaly values in x.
1220  intx_dza(i,j) = c1_90*(7.0*(intp(1)+intp(5)) + 32.0*(intp(2)+intp(4)) + &
1221  12.0*intp(3))
1222  enddo ; enddo ; endif
1223 
1224  if (present(inty_dza)) then ; do j=jsq,jeq ; do i=hi%isc,hi%iec
1225  ! hWght is the distance measure by which the cell is violation of
1226  ! hydrostatic consistency. For large hWght we bias the interpolation of
1227  ! T & S along the top and bottom integrals, akin to thickness weighting.
1228  hwght = 0.0
1229  if (do_massweight) &
1230  hwght = max(0., bathyp(i,j)-p_t(i,j+1), bathyp(i,j+1)-p_t(i,j))
1231  if (hwght > 0.) then
1232  hl = (p_b(i,j) - p_t(i,j)) + dp_neglect
1233  hr = (p_b(i,j+1) - p_t(i,j+1)) + dp_neglect
1234  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
1235  idenom = 1.0 / ( hwght*(hr + hl) + hl*hr )
1236  hwt_ll = (hwght*hl + hr*hl) * idenom ; hwt_lr = (hwght*hr) * idenom
1237  hwt_rr = (hwght*hr + hr*hl) * idenom ; hwt_rl = (hwght*hl) * idenom
1238  else
1239  hwt_ll = 1.0 ; hwt_lr = 0.0 ; hwt_rr = 1.0 ; hwt_rl = 0.0
1240  endif
1241 
1242  intp(1) = dza(i,j) ; intp(5) = dza(i,j+1)
1243  do m=2,4
1244  wt_l = 0.25*real(5-m) ; wt_r = 1.0-wt_l
1245  wtt_l = wt_l*hwt_ll + wt_r*hwt_rl ; wtt_r = wt_l*hwt_lr + wt_r*hwt_rr
1246 
1247  ! T, S, and p are interpolated in the horizontal. The p interpolation
1248  ! is linear, but for T and S it may be thickness weighted.
1249  p5(1) = rl2_t2_to_pa * (wt_l*p_b(i,j) + wt_r*p_b(i,j+1))
1250  dp = wt_l*(p_b(i,j) - p_t(i,j)) + wt_r*(p_b(i,j+1) - p_t(i,j+1))
1251  t5(1) = wtt_l*t(i,j) + wtt_r*t(i,j+1)
1252  s5(1) = wtt_l*s(i,j) + wtt_r*s(i,j+1)
1253  do n=2,5
1254  t5(n) = t5(1) ; s5(n) = s5(1) ; p5(n) = rl2_t2_to_pa * (p5(n-1) - 0.25*dp)
1255  enddo
1256  if (sv_scale /= 1.0) then
1257  call calculate_spec_vol(t5, s5, p5, a5, 1, 5, eos, alpha_ref_mks, scale=sv_scale)
1258  else
1259  call calculate_spec_vol(t5, s5, p5, a5, 1, 5, eos, alpha_ref_mks)
1260  endif
1261 
1262  ! Use Boole's rule to estimate the interface height anomaly change.
1263  intp(m) = dp*( c1_90*(7.0*(a5(1)+a5(5)) + 32.0*(a5(2)+a5(4)) + &
1264  12.0*a5(3)))
1265  enddo
1266  ! Use Boole's rule to integrate the interface height anomaly values in y.
1267  inty_dza(i,j) = c1_90*(7.0*(intp(1)+intp(5)) + 32.0*(intp(2)+intp(4)) + &
1268  12.0*intp(3))
1269  enddo ; enddo ; endif
1270 

◆ int_spec_vol_dp_generic_plm()

subroutine, public mom_density_integrals::int_spec_vol_dp_generic_plm ( real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  T_t,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  T_b,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  S_t,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  S_b,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  p_t,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  p_b,
real, intent(in)  alpha_ref,
real, intent(in)  dP_neglect,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(in)  bathyP,
type(hor_index_type), intent(in)  HI,
type(eos_type), pointer  EOS,
type(unit_scale_type), intent(in)  US,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(inout)  dza,
real, dimension( hi %isd: hi %ied, hi %jsd: hi %jed), intent(inout), optional  intp_dza,
real, dimension( hi %isdb: hi %iedb, hi %jsd: hi %jed), intent(inout), optional  intx_dza,
real, dimension( hi %isd: hi %ied, hi %jsdb: hi %jedb), intent(inout), optional  inty_dza,
logical, intent(in), optional  useMassWghtInterp 
)

This subroutine calculates integrals of specific volume anomalies in pressure across layers, which are required for calculating the finite-volume form pressure accelerations in a non-Boussinesq model. There are essentially no free assumptions, apart from the use of Boole's rule quadrature to do the integrals.

Parameters
[in]hiA horizontal index type structure.
[in]t_tPotential temperature at the top of the layer [degC]
[in]t_bPotential temperature at the bottom of the layer [degC]
[in]s_tSalinity at the top the layer [ppt]
[in]s_bSalinity at the bottom the layer [ppt]
[in]p_tPressure atop the layer [R L2 T-2 ~> Pa] or [Pa]
[in]p_bPressure below the layer [R L2 T-2 ~> Pa] or [Pa]
[in]alpha_refA mean specific volume that is subtracted out to reduce the magnitude of each of the integrals [R-1 ~> m3 kg-1] The calculation is mathematically identical with different values of alpha_ref, but alpha_ref alters the effects of roundoff, and answers do change.
[in]dp_neglect!< A miniscule pressure change with the same units as p_t [R L2 T-2 ~> Pa] or [Pa]
[in]bathypThe pressure at the bathymetry [R L2 T-2 ~> Pa] or [Pa]
eosEquation of state structure
[in]usA dimensional unit scaling type
[in,out]dzaThe change in the geopotential anomaly
[in,out]intp_dzaThe integral in pressure through the layer of
[in,out]intx_dzaThe integral in x of the difference between
[in,out]inty_dzaThe integral in y of the difference between
[in]usemasswghtinterpIf true, uses mass weighting to interpolate T/S for top and bottom integrals.

Definition at line 1280 of file MOM_density_integrals.F90.

1280  type(hor_index_type), intent(in) :: HI !< A horizontal index type structure.
1281  real, dimension(SZI_(HI),SZJ_(HI)), &
1282  intent(in) :: T_t !< Potential temperature at the top of the layer [degC]
1283  real, dimension(SZI_(HI),SZJ_(HI)), &
1284  intent(in) :: T_b !< Potential temperature at the bottom of the layer [degC]
1285  real, dimension(SZI_(HI),SZJ_(HI)), &
1286  intent(in) :: S_t !< Salinity at the top the layer [ppt]
1287  real, dimension(SZI_(HI),SZJ_(HI)), &
1288  intent(in) :: S_b !< Salinity at the bottom the layer [ppt]
1289  real, dimension(SZI_(HI),SZJ_(HI)), &
1290  intent(in) :: p_t !< Pressure atop the layer [R L2 T-2 ~> Pa] or [Pa]
1291  real, dimension(SZI_(HI),SZJ_(HI)), &
1292  intent(in) :: p_b !< Pressure below the layer [R L2 T-2 ~> Pa] or [Pa]
1293  real, intent(in) :: alpha_ref !< A mean specific volume that is subtracted out
1294  !! to reduce the magnitude of each of the integrals [R-1 ~> m3 kg-1]
1295  !! The calculation is mathematically identical with different values of
1296  !! alpha_ref, but alpha_ref alters the effects of roundoff, and
1297  !! answers do change.
1298  real, intent(in) :: dP_neglect !<!< A miniscule pressure change with
1299  !! the same units as p_t [R L2 T-2 ~> Pa] or [Pa]
1300  real, dimension(SZI_(HI),SZJ_(HI)), &
1301  intent(in) :: bathyP !< The pressure at the bathymetry [R L2 T-2 ~> Pa] or [Pa]
1302  type(EOS_type), pointer :: EOS !< Equation of state structure
1303  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
1304  real, dimension(SZI_(HI),SZJ_(HI)), &
1305  intent(inout) :: dza !< The change in the geopotential anomaly
1306  !! across the layer [L2 T-2 ~> m2 s-2]
1307  real, dimension(SZI_(HI),SZJ_(HI)), &
1308  optional, intent(inout) :: intp_dza !< The integral in pressure through the layer of
1309  !! the geopotential anomaly relative to the anomaly at the bottom of the
1310  !! layer [R L4 T-4 ~> Pa m2 s-2] or [Pa m2 s-2]
1311  real, dimension(SZIB_(HI),SZJ_(HI)), &
1312  optional, intent(inout) :: intx_dza !< The integral in x of the difference between
1313  !! the geopotential anomaly at the top and bottom of the layer divided
1314  !! by the x grid spacing [L2 T-2 ~> m2 s-2] or [m2 s-2]
1315  real, dimension(SZI_(HI),SZJB_(HI)), &
1316  optional, intent(inout) :: inty_dza !< The integral in y of the difference between
1317  !! the geopotential anomaly at the top and bottom of the layer divided
1318  !! by the y grid spacing [L2 T-2 ~> m2 s-2] or [m2 s-2]
1319  logical, optional, intent(in) :: useMassWghtInterp !< If true, uses mass weighting
1320  !! to interpolate T/S for top and bottom integrals.
1321 
1322 ! This subroutine calculates analytical and nearly-analytical integrals in
1323 ! pressure across layers of geopotential anomalies, which are required for
1324 ! calculating the finite-volume form pressure accelerations in a non-Boussinesq
1325 ! model. There are essentially no free assumptions, apart from the use of
1326 ! Boole's rule to do the horizontal integrals, and from a truncation in the
1327 ! series for log(1-eps/1+eps) that assumes that |eps| < 0.34.
1328 
1329  real :: T5(5) ! Temperatures at five quadrature points [degC]
1330  real :: S5(5) ! Salinities at five quadrature points [ppt]
1331  real :: p5(5) ! Pressures at five quadrature points, scaled back to Pa as necessary [Pa]
1332  real :: a5(5) ! Specific volumes at five quadrature points [R-1 ~> m3 kg-1] or [m3 kg-1]
1333  real :: T15(15) ! Temperatures at fifteen interior quadrature points [degC]
1334  real :: S15(15) ! Salinities at fifteen interior quadrature points [ppt]
1335  real :: p15(15) ! Pressures at fifteen quadrature points, scaled back to Pa as necessary [Pa]
1336  real :: a15(15) ! Specific volumes at fifteen quadrature points [R-1 ~> m3 kg-1] or [m3 kg-1]
1337  real :: wt_t(5), wt_b(5) ! Weights of top and bottom values at quadrature points [nondim]
1338  real :: T_top, T_bot, S_top, S_bot, P_top, P_bot
1339 
1340  real :: alpha_anom ! The depth averaged specific density anomaly [m3 kg-1]
1341  real :: dp ! The pressure change through a layer [R L2 T-2 ~> Pa]
1342  real :: dp_90(2:4) ! The pressure change through a layer divided by 90 [R L2 T-2 ~> Pa]
1343  real :: hWght ! A pressure-thickness below topography [R L2 T-2 ~> Pa]
1344  real :: hL, hR ! Pressure-thicknesses of the columns to the left and right [R L2 T-2 ~> Pa]
1345  real :: alpha_ref_mks ! The reference specific volume in MKS units, never rescaled from m3 kg-1 [m3 kg-1]
1346  real :: iDenom ! The inverse of the denominator in the weights [T4 R-2 L-4 ~> Pa-2]
1347  real :: hWt_LL, hWt_LR ! hWt_LA is the weighted influence of A on the left column [nondim]
1348  real :: hWt_RL, hWt_RR ! hWt_RA is the weighted influence of A on the right column [nondim]
1349  real :: wt_L, wt_R ! The linear weights of the left and right columns [nondim]
1350  real :: wtT_L, wtT_R ! The weights for tracers from the left and right columns [nondim]
1351  real :: intp(5) ! The integrals of specific volume with pressure at the
1352  ! 5 sub-column locations [L2 T-2 ~> m2 s-2]
1353  real :: RL2_T2_to_Pa ! A unit conversion factor from the rescaled units of pressure to Pa [Pa T2 R-1 L-2 ~> 1]
1354  real :: SV_scale ! A multiplicative factor by which to scale specific
1355  ! volume from m3 kg-1 to the desired units [kg m-3 R-1 ~> 1]
1356  real, parameter :: C1_90 = 1.0/90.0 ! A rational constant.
1357  logical :: do_massWeight ! Indicates whether to do mass weighting.
1358  integer :: Isq, Ieq, Jsq, Jeq, i, j, m, n, pos
1359 
1360  isq = hi%IscB ; ieq = hi%IecB ; jsq = hi%JscB ; jeq = hi%JecB
1361 
1362  do_massweight = .false.
1363  if (present(usemasswghtinterp)) do_massweight = usemasswghtinterp
1364 
1365  sv_scale = us%R_to_kg_m3
1366  rl2_t2_to_pa = us%RL2_T2_to_Pa
1367  alpha_ref_mks = alpha_ref * us%kg_m3_to_R
1368 
1369  do n = 1, 5 ! Note that these are reversed from int_density_dz.
1370  wt_t(n) = 0.25 * real(n-1)
1371  wt_b(n) = 1.0 - wt_t(n)
1372  enddo
1373 
1374  ! 1. Compute vertical integrals
1375  do j=jsq,jeq+1; do i=isq,ieq+1
1376  dp = p_b(i,j) - p_t(i,j)
1377  do n=1,5 ! T, S and p are linearly interpolated in the vertical.
1378  p5(n) = rl2_t2_to_pa * (wt_t(n) * p_t(i,j) + wt_b(n) * p_b(i,j))
1379  s5(n) = wt_t(n) * s_t(i,j) + wt_b(n) * s_b(i,j)
1380  t5(n) = wt_t(n) * t_t(i,j) + wt_b(n) * t_b(i,j)
1381  enddo
1382  if (sv_scale /= 1.0) then
1383  call calculate_spec_vol(t5, s5, p5, a5, 1, 5, eos, alpha_ref_mks, scale=sv_scale)
1384  else
1385  call calculate_spec_vol(t5, s5, p5, a5, 1, 5, eos, alpha_ref_mks)
1386  endif
1387 
1388  ! Use Boole's rule to estimate the interface height anomaly change.
1389  alpha_anom = c1_90*((7.0*(a5(1)+a5(5)) + 32.0*(a5(2)+a5(4))) + 12.0*a5(3))
1390  dza(i,j) = dp*alpha_anom
1391  ! Use a Boole's-rule-like fifth-order accurate estimate of the double integral of
1392  ! the interface height anomaly.
1393  if (present(intp_dza)) intp_dza(i,j) = 0.5*dp**2 * &
1394  (alpha_anom - c1_90*(16.0*(a5(4)-a5(2)) + 7.0*(a5(5)-a5(1))) )
1395  enddo ; enddo
1396 
1397  ! 2. Compute horizontal integrals in the x direction
1398  if (present(intx_dza)) then ; do j=hi%jsc,hi%jec ; do i=isq,ieq
1399  ! hWght is the distance measure by which the cell is violation of
1400  ! hydrostatic consistency. For large hWght we bias the interpolation
1401  ! of T,S along the top and bottom integrals, almost like thickness
1402  ! weighting. Note: To work in terrain following coordinates we could
1403  ! offset this distance by the layer thickness to replicate other models.
1404  hwght = 0.0
1405  if (do_massweight) &
1406  hwght = max(0., bathyp(i,j)-p_t(i+1,j), bathyp(i+1,j)-p_t(i,j))
1407  if (hwght > 0.) then
1408  hl = (p_b(i,j) - p_t(i,j)) + dp_neglect
1409  hr = (p_b(i+1,j) - p_t(i+1,j)) + dp_neglect
1410  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
1411  idenom = 1.0 / ( hwght*(hr + hl) + hl*hr )
1412  hwt_ll = (hwght*hl + hr*hl) * idenom ; hwt_lr = (hwght*hr) * idenom
1413  hwt_rr = (hwght*hr + hr*hl) * idenom ; hwt_rl = (hwght*hl) * idenom
1414  else
1415  hwt_ll = 1.0 ; hwt_lr = 0.0 ; hwt_rr = 1.0 ; hwt_rl = 0.0
1416  endif
1417 
1418  do m=2,4
1419  wt_l = 0.25*real(5-m) ; wt_r = 1.0-wt_l
1420  wtt_l = wt_l*hwt_ll + wt_r*hwt_rl ; wtt_r = wt_l*hwt_lr + wt_r*hwt_rr
1421 
1422  ! T, S, and p are interpolated in the horizontal. The p interpolation
1423  ! is linear, but for T and S it may be thickness weighted.
1424  p_top = wt_l*p_t(i,j) + wt_r*p_t(i+1,j)
1425  p_bot = wt_l*p_b(i,j) + wt_r*p_b(i+1,j)
1426  t_top = wtt_l*t_t(i,j) + wtt_r*t_t(i+1,j)
1427  t_bot = wtt_l*t_b(i,j) + wtt_r*t_b(i+1,j)
1428  s_top = wtt_l*s_t(i,j) + wtt_r*s_t(i+1,j)
1429  s_bot = wtt_l*s_b(i,j) + wtt_r*s_b(i+1,j)
1430  dp_90(m) = c1_90*(p_bot - p_top)
1431 
1432  ! Salinity, temperature and pressure with linear interpolation in the vertical.
1433  pos = (m-2)*5
1434  do n=1,5
1435  p15(pos+n) = rl2_t2_to_pa * (wt_t(n) * p_top + wt_b(n) * p_bot)
1436  s15(pos+n) = wt_t(n) * s_top + wt_b(n) * s_bot
1437  t15(pos+n) = wt_t(n) * t_top + wt_b(n) * t_bot
1438  enddo
1439  enddo
1440 
1441  if (sv_scale /= 1.0) then
1442  call calculate_spec_vol(t15, s15, p15, a15, 1, 15, eos, alpha_ref_mks, scale=sv_scale)
1443  else
1444  call calculate_spec_vol(t15, s15, p15, a15, 1, 15, eos, alpha_ref_mks)
1445  endif
1446 
1447  intp(1) = dza(i,j) ; intp(5) = dza(i+1,j)
1448  do m=2,4
1449  ! Use Boole's rule to estimate the interface height anomaly change.
1450  ! The integrals at the ends of the segment are already known.
1451  pos = (m-2)*5
1452  intp(m) = dp_90(m)*((7.0*(a15(pos+1)+a15(pos+5)) + &
1453  32.0*(a15(pos+2)+a15(pos+4))) + 12.0*a15(pos+3))
1454  enddo
1455  ! Use Boole's rule to integrate the interface height anomaly values in x.
1456  intx_dza(i,j) = c1_90*((7.0*(intp(1)+intp(5)) + 32.0*(intp(2)+intp(4))) + &
1457  12.0*intp(3))
1458  enddo ; enddo ; endif
1459 
1460  ! 3. Compute horizontal integrals in the y direction
1461  if (present(inty_dza)) then ; do j=jsq,jeq ; do i=hi%isc,hi%iec
1462  ! hWght is the distance measure by which the cell is violation of
1463  ! hydrostatic consistency. For large hWght we bias the interpolation
1464  ! of T,S along the top and bottom integrals, like thickness weighting.
1465  hwght = 0.0
1466  if (do_massweight) &
1467  hwght = max(0., bathyp(i,j)-p_t(i,j+1), bathyp(i,j+1)-p_t(i,j))
1468  if (hwght > 0.) then
1469  hl = (p_b(i,j) - p_t(i,j)) + dp_neglect
1470  hr = (p_b(i,j+1) - p_t(i,j+1)) + dp_neglect
1471  hwght = hwght * ( (hl-hr)/(hl+hr) )**2
1472  idenom = 1.0 / ( hwght*(hr + hl) + hl*hr )
1473  hwt_ll = (hwght*hl + hr*hl) * idenom ; hwt_lr = (hwght*hr) * idenom
1474  hwt_rr = (hwght*hr + hr*hl) * idenom ; hwt_rl = (hwght*hl) * idenom
1475  else
1476  hwt_ll = 1.0 ; hwt_lr = 0.0 ; hwt_rr = 1.0 ; hwt_rl = 0.0
1477  endif
1478 
1479  do m=2,4
1480  wt_l = 0.25*real(5-m) ; wt_r = 1.0-wt_l
1481  wtt_l = wt_l*hwt_ll + wt_r*hwt_rl ; wtt_r = wt_l*hwt_lr + wt_r*hwt_rr
1482 
1483  ! T, S, and p are interpolated in the horizontal. The p interpolation
1484  ! is linear, but for T and S it may be thickness weighted.
1485  p_top = wt_l*p_t(i,j) + wt_r*p_t(i,j+1)
1486  p_bot = wt_l*p_b(i,j) + wt_r*p_b(i,j+1)
1487  t_top = wtt_l*t_t(i,j) + wtt_r*t_t(i,j+1)
1488  t_bot = wtt_l*t_b(i,j) + wtt_r*t_b(i,j+1)
1489  s_top = wtt_l*s_t(i,j) + wtt_r*s_t(i,j+1)
1490  s_bot = wtt_l*s_b(i,j) + wtt_r*s_b(i,j+1)
1491  dp_90(m) = c1_90*(p_bot - p_top)
1492 
1493  ! Salinity, temperature and pressure with linear interpolation in the vertical.
1494  pos = (m-2)*5
1495  do n=1,5
1496  p15(pos+n) = rl2_t2_to_pa * (wt_t(n) * p_top + wt_b(n) * p_bot)
1497  s15(pos+n) = wt_t(n) * s_top + wt_b(n) * s_bot
1498  t15(pos+n) = wt_t(n) * t_top + wt_b(n) * t_bot
1499  enddo
1500  enddo
1501 
1502  if (sv_scale /= 1.0) then
1503  call calculate_spec_vol(t15, s15, p15, a15, 1, 15, eos, alpha_ref_mks, scale=sv_scale)
1504  else
1505  call calculate_spec_vol(t15, s15, p15, a15, 1, 15, eos, alpha_ref_mks)
1506  endif
1507 
1508  intp(1) = dza(i,j) ; intp(5) = dza(i,j+1)
1509  do m=2,4
1510  ! Use Boole's rule to estimate the interface height anomaly change.
1511  ! The integrals at the ends of the segment are already known.
1512  pos = (m-2)*5
1513  intp(m) = dp_90(m) * ((7.0*(a15(pos+1)+a15(pos+5)) + &
1514  32.0*(a15(pos+2)+a15(pos+4))) + 12.0*a15(pos+3))
1515  enddo
1516  ! Use Boole's rule to integrate the interface height anomaly values in x.
1517  inty_dza(i,j) = c1_90*((7.0*(intp(1)+intp(5)) + 32.0*(intp(2)+intp(4))) + &
1518  12.0*intp(3))
1519  enddo ; enddo ; endif
1520 

◆ int_specific_vol_dp()

subroutine, public mom_density_integrals::int_specific_vol_dp ( real, dimension(szi_(hi),szj_(hi)), intent(in)  T,
real, dimension(szi_(hi),szj_(hi)), intent(in)  S,
real, dimension(szi_(hi),szj_(hi)), intent(in)  p_t,
real, dimension(szi_(hi),szj_(hi)), intent(in)  p_b,
real, intent(in)  alpha_ref,
type(hor_index_type), intent(in)  HI,
type(eos_type), pointer  EOS,
type(unit_scale_type), intent(in)  US,
real, dimension(szi_(hi),szj_(hi)), intent(inout)  dza,
real, dimension(szi_(hi),szj_(hi)), intent(inout), optional  intp_dza,
real, dimension(szib_(hi),szj_(hi)), intent(inout), optional  intx_dza,
real, dimension(szi_(hi),szjb_(hi)), intent(inout), optional  inty_dza,
integer, intent(in), optional  halo_size,
real, dimension(szi_(hi),szj_(hi)), intent(in), optional  bathyP,
real, intent(in), optional  dP_tiny,
logical, intent(in), optional  useMassWghtInterp 
)

Calls the appropriate subroutine to calculate analytical and nearly-analytical integrals in pressure across layers of geopotential anomalies, which are required for calculating the finite-volume form pressure accelerations in a non-Boussinesq model. There are essentially no free assumptions, apart from the use of Boole's rule to do the horizontal integrals, and from a truncation in the series for log(1-eps/1+eps) that assumes that |eps| < 0.34.

Parameters
[in]hiThe horizontal index structure
[in]tPotential temperature referenced to the surface [degC]
[in]sSalinity [ppt]
[in]p_tPressure at the top of the layer [R L2 T-2 ~> Pa] or [Pa]
[in]p_bPressure at the bottom of the layer [R L2 T-2 ~> Pa] or [Pa]
[in]alpha_refA mean specific volume that is subtracted out to reduce the magnitude of each of the integrals [R-1 ~> m3 kg-1] The calculation is mathematically identical with different values of alpha_ref, but this reduces the effects of roundoff.
eosEquation of state structure
[in]usA dimensional unit scaling type
[in,out]dzaThe change in the geopotential anomaly across
[in,out]intp_dzaThe integral in pressure through the layer of the
[in,out]intx_dzaThe integral in x of the difference between the
[in,out]inty_dzaThe integral in y of the difference between the
[in]halo_sizeThe width of halo points on which to calculate dza.
[in]bathypThe pressure at the bathymetry [R L2 T-2 ~> Pa] or [Pa]
[in]dp_tinyA minuscule pressure change with the same units as p_t [R L2 T-2 ~> Pa] or [Pa]
[in]usemasswghtinterpIf true, uses mass weighting to interpolate T/S for top and bottom integrals.

Definition at line 1007 of file MOM_density_integrals.F90.

1007  type(hor_index_type), intent(in) :: HI !< The horizontal index structure
1008  real, dimension(SZI_(HI),SZJ_(HI)), &
1009  intent(in) :: T !< Potential temperature referenced to the surface [degC]
1010  real, dimension(SZI_(HI),SZJ_(HI)), &
1011  intent(in) :: S !< Salinity [ppt]
1012  real, dimension(SZI_(HI),SZJ_(HI)), &
1013  intent(in) :: p_t !< Pressure at the top of the layer [R L2 T-2 ~> Pa] or [Pa]
1014  real, dimension(SZI_(HI),SZJ_(HI)), &
1015  intent(in) :: p_b !< Pressure at the bottom of the layer [R L2 T-2 ~> Pa] or [Pa]
1016  real, intent(in) :: alpha_ref !< A mean specific volume that is subtracted out
1017  !! to reduce the magnitude of each of the integrals [R-1 ~> m3 kg-1]
1018  !! The calculation is mathematically identical with different values of
1019  !! alpha_ref, but this reduces the effects of roundoff.
1020  type(EOS_type), pointer :: EOS !< Equation of state structure
1021  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
1022  real, dimension(SZI_(HI),SZJ_(HI)), &
1023  intent(inout) :: dza !< The change in the geopotential anomaly across
1024  !! the layer [L2 T-2 ~> m2 s-2] or [m2 s-2]
1025  real, dimension(SZI_(HI),SZJ_(HI)), &
1026  optional, intent(inout) :: intp_dza !< The integral in pressure through the layer of the
1027  !! geopotential anomaly relative to the anomaly at the bottom of the
1028  !! layer [R L4 T-4 ~> Pa m2 s-2] or [Pa m2 s-2]
1029  real, dimension(SZIB_(HI),SZJ_(HI)), &
1030  optional, intent(inout) :: intx_dza !< The integral in x of the difference between the
1031  !! geopotential anomaly at the top and bottom of the layer divided by
1032  !! the x grid spacing [L2 T-2 ~> m2 s-2] or [m2 s-2]
1033  real, dimension(SZI_(HI),SZJB_(HI)), &
1034  optional, intent(inout) :: inty_dza !< The integral in y of the difference between the
1035  !! geopotential anomaly at the top and bottom of the layer divided by
1036  !! the y grid spacing [L2 T-2 ~> m2 s-2] or [m2 s-2]
1037  integer, optional, intent(in) :: halo_size !< The width of halo points on which to calculate dza.
1038  real, dimension(SZI_(HI),SZJ_(HI)), &
1039  optional, intent(in) :: bathyP !< The pressure at the bathymetry [R L2 T-2 ~> Pa] or [Pa]
1040  real, optional, intent(in) :: dP_tiny !< A minuscule pressure change with
1041  !! the same units as p_t [R L2 T-2 ~> Pa] or [Pa]
1042  logical, optional, intent(in) :: useMassWghtInterp !< If true, uses mass weighting
1043  !! to interpolate T/S for top and bottom integrals.
1044 
1045  if (eos_quadrature(eos)) then
1046  call int_spec_vol_dp_generic_pcm(t, s, p_t, p_b, alpha_ref, hi, eos, us, &
1047  dza, intp_dza, intx_dza, inty_dza, halo_size, &
1048  bathyp, dp_tiny, usemasswghtinterp)
1049  else
1050  call analytic_int_specific_vol_dp(t, s, p_t, p_b, alpha_ref, hi, eos, &
1051  dza, intp_dza, intx_dza, inty_dza, halo_size, &
1052  bathyp, dp_tiny, usemasswghtinterp)
1053  endif
1054