MOM6
MOM_PressureForce_analytic_FV.F90
1 !> Analytically integrated finite volume pressure gradient
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_diag_mediator, only : post_data, register_diag_field
7 use mom_diag_mediator, only : safe_alloc_ptr, diag_ctrl, time_type
8 use mom_error_handler, only : mom_error, fatal, warning, is_root_pe
10 use mom_grid, only : ocean_grid_type
11 use mom_pressureforce_mont, only : set_pbce_bouss, set_pbce_nonbouss
12 use mom_tidal_forcing, only : calc_tidal_forcing, tidal_forcing_cs
17 use mom_eos, only : int_density_dz, int_specific_vol_dp
18 use mom_eos, only : int_density_dz_generic_plm, int_density_dz_generic_ppm
19 use mom_eos, only : int_spec_vol_dp_generic_plm
20 use mom_eos, only : int_density_dz_generic, int_spec_vol_dp_generic
21 use mom_ale, only : pressure_gradient_plm, pressure_gradient_ppm, ale_cs
22 
23 implicit none ; private
24 
25 #include <MOM_memory.h>
26 
27 public pressureforce_afv, pressureforce_afv_init, pressureforce_afv_end
28 public pressureforce_afv_bouss, pressureforce_afv_nonbouss
29 
30 ! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
31 ! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
32 ! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
33 ! vary with the Boussinesq approximation, the Boussinesq variant is given first.
34 
35 !> Finite volume pressure gradient control structure
36 type, public :: pressureforce_afv_cs ; private
37  logical :: tides !< If true, apply tidal momentum forcing.
38  real :: rho0 !< The density used in the Boussinesq
39  !! approximation [kg m-3].
40  real :: gfs_scale !< A scaling of the surface pressure gradients to
41  !! allow the use of a reduced gravity model [nondim].
42  type(time_type), pointer :: time !< A pointer to the ocean model's clock.
43  type(diag_ctrl), pointer :: diag !< A structure that is used to regulate the
44  !! timing of diagnostic output.
45  logical :: usemasswghtinterp !< Use mass weighting in T/S interpolation
46  logical :: boundary_extrap !< Indicate whether high-order boundary
47  !! extrapolation should be used within boundary cells
48 
49  logical :: reconstruct !< If true, polynomial profiles of T & S will be
50  !! reconstructed and used in the integrals for the
51  !! finite volume pressure gradient calculation.
52  !! The default depends on whether regridding is being used.
53 
54  integer :: recon_scheme !< Order of the polynomial of the reconstruction of T & S
55  !! for the finite volume pressure gradient calculation.
56  !! By the default (1) is for a piecewise linear method
57 
58  integer :: id_e_tidal = -1 !< Diagnostic identifier
59  type(tidal_forcing_cs), pointer :: tides_csp => null() !< Tides control structure
60 end type pressureforce_afv_cs
61 
62 contains
63 
64 !> Thin interface between the model and the Boussinesq and non-Boussinesq
65 !! pressure force routines.
66 subroutine pressureforce_afv(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm, pbce, eta)
67  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
68  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure
69  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
70  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2]
71  type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamic variables
72  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(out) :: pfu !< Zonal acceleration [m s-2]
73  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(out) :: pfv !< Meridional acceleration [m s-2]
74  type(pressureforce_afv_cs), pointer :: cs !< Finite volume PGF control structure
75  type(ale_cs), pointer :: ale_csp !< ALE control structure
76  real, dimension(:,:), optional, pointer :: p_atm !< The pressure at the ice-ocean
77  !! or atmosphere-ocean interface [Pa].
78  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), optional, intent(out) :: pbce !< The baroclinic pressure
79  !! anomaly in each layer due to eta anomalies
80  !! [m2 s-2 H-1 ~> m s-2 or m4 s-2 kg-1].
81  real, dimension(SZI_(G),SZJ_(G)), optional, intent(out) :: eta !< The bottom mass used to
82  !! calculate PFu and PFv [H ~> m or kg m-2], with any tidal
83  !! contributions or compressibility compensation.
84 
85  if (gv%Boussinesq) then
86  call pressureforce_afv_bouss(h, tv, pfu, pfv, g, gv, us, cs, ale_csp, p_atm, pbce, eta)
87  else
88  call pressureforce_afv_nonbouss(h, tv, pfu, pfv, g, gv, us, cs, ale_csp, p_atm, pbce, eta)
89  endif
90 
91 end subroutine pressureforce_afv
92 
93 !> \brief Non-Boussinesq analytically-integrated finite volume form of pressure gradient
94 !!
95 !! Determines the acceleration due to hydrostatic pressure forces, using
96 !! the analytic finite volume form of the Pressure gradient, and does not
97 !! make the Boussinesq approximation.
98 !!
99 !! To work, the following fields must be set outside of the usual (is:ie,js:je)
100 !! range before this subroutine is called:
101 !! h(isB:ie+1,jsB:je+1), T(isB:ie+1,jsB:je+1), and S(isB:ie+1,jsB:je+1).
102 subroutine pressureforce_afv_nonbouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm, pbce, eta)
103  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
104  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure
105  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
106  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness [H ~> kg/m2]
107  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables
108  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(out) :: pfu !< Zonal acceleration [m s-2]
109  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(out) :: pfv !< Meridional acceleration [m s-2]
110  type(pressureforce_afv_cs), pointer :: cs !< Finite volume PGF control structure
111  type(ale_cs), pointer :: ale_csp !< ALE control structure
112  real, dimension(:,:), optional, pointer :: p_atm !< The pressure at the ice-ocean
113  !! or atmosphere-ocean interface [Pa].
114  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), optional, intent(out) :: pbce !< The baroclinic pressure
115  !! anomaly in each layer due to eta anomalies
116  !! [m2 s-2 H-1 ~> m s-2 or m4 s-2 kg-1].
117  real, dimension(SZI_(G),SZJ_(G)), optional, intent(out) :: eta !< The bottom mass used to
118  !! calculate PFu and PFv [H ~> m or kg m-2], with any tidal
119  !! contributions or compressibility compensation.
120  ! Local variables
121  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1) :: p ! Interface pressure [Pa].
122  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), target :: &
123  t_tmp, & ! Temporary array of temperatures where layers that are lighter
124  ! than the mixed layer have the mixed layer's properties [degC].
125  s_tmp ! Temporary array of salinities where layers that are lighter
126  ! than the mixed layer have the mixed layer's properties [ppt].
127  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
128  s_t, & ! Top and bottom edge values for linear reconstructions
129  s_b, & ! of salinity within each layer [ppt].
130  t_t, & ! Top and bottom edge values for linear reconstructions
131  t_b ! of temperature within each layer [degC].
132  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
133  dza, & ! The change in geopotential anomaly between the top and bottom
134  ! of a layer [m2 s-2].
135  intp_dza ! The vertical integral in depth of the pressure anomaly less
136  ! the pressure anomaly at the top of the layer [Pa m2 s-2].
137  real, dimension(SZI_(G),SZJ_(G)) :: &
138  dp, & ! The (positive) change in pressure across a layer [Pa].
139  ssh, & ! The sea surface height anomaly, in depth units [Z ~> m].
140  e_tidal, & ! The bottom geopotential anomaly due to tidal forces from
141  ! astronomical sources and self-attraction and loading [Z ~> m].
142  dm, & ! The barotropic adjustment to the Montgomery potential to
143  ! account for a reduced gravity model [m2 s-2].
144  za ! The geopotential anomaly (i.e. g*e + alpha_0*pressure) at the
145  ! interface atop a layer [m2 s-2].
146 
147  real, dimension(SZI_(G)) :: rho_cv_bl ! The coordinate potential density in the deepest variable
148  ! density near-surface layer [kg m-3].
149  real, dimension(SZIB_(G),SZJ_(G)) :: &
150  intx_za ! The zonal integral of the geopotential anomaly along the
151  ! interface below a layer, divided by the grid spacing [m2 s-2].
152  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)) :: &
153  intx_dza ! The change in intx_za through a layer [m2 s-2].
154  real, dimension(SZI_(G),SZJB_(G)) :: &
155  inty_za ! The meridional integral of the geopotential anomaly along the
156  ! interface below a layer, divided by the grid spacing [m2 s-2].
157  real, dimension(SZI_(G),SZJB_(G),SZK_(G)) :: &
158  inty_dza ! The change in inty_za through a layer [m2 s-2].
159  real :: p_ref(szi_(g)) ! The pressure used to calculate the coordinate
160  ! density, [Pa] (usually 2e7 Pa = 2000 dbar).
161 
162  real :: dp_neglect ! A thickness that is so small it is usually lost
163  ! in roundoff and can be neglected [Pa].
164  real :: g_earth_z ! A scaled version of g_Earth [m2 Z-1 s-2 ~> m s-2].
165  real :: i_gearth ! The inverse of g_Earth_z [s2 Z m-2 ~> s2 m-1]
166  real :: alpha_anom ! The in-situ specific volume, averaged over a
167  ! layer, less alpha_ref [m3 kg-1].
168  logical :: use_p_atm ! If true, use the atmospheric pressure.
169  logical :: use_ale ! If true, use an ALE pressure reconstruction.
170  logical :: use_eos ! If true, density is calculated from T & S using an
171  ! equation of state.
172  type(thermo_var_ptrs) :: tv_tmp! A structure of temporary T & S.
173 
174  real :: alpha_ref ! A reference specific volume [m3 kg-1], that is used
175  ! to reduce the impact of truncation errors.
176  real :: rho_in_situ(szi_(g)) ! The in situ density [kg m-3].
177  real :: pa_to_h ! A factor to convert from Pa to the thicknesss units (H).
178 ! real :: oneatm = 101325.0 ! 1 atm in [Pa] = [kg m-1 s-2]
179  real, parameter :: c1_6 = 1.0/6.0
180  integer :: is, ie, js, je, isq, ieq, jsq, jeq, nz, nkmb
181  integer :: i, j, k
182 
183  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
184  nkmb=gv%nk_rho_varies
185  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
186 
187  if (.not.associated(cs)) call mom_error(fatal, &
188  "MOM_PressureForce_AFV_nonBouss: Module must be initialized before it is used.")
189 
190  use_p_atm = .false.
191  if (present(p_atm)) then ; if (associated(p_atm)) use_p_atm = .true. ; endif
192  use_eos = associated(tv%eqn_of_state)
193  use_ale = .false.
194  if (associated(ale_csp)) use_ale = cs%reconstruct .and. use_eos
195 
196  dp_neglect = gv%H_to_Pa * gv%H_subroundoff
197  alpha_ref = 1.0/cs%Rho0
198  g_earth_z = us%L_T_to_m_s**2 * gv%g_Earth
199  i_gearth = 1.0 / g_earth_z
200 
201  if (use_p_atm) then
202  !$OMP parallel do default(shared)
203  do j=jsq,jeq+1 ; do i=isq,ieq+1
204  p(i,j,1) = p_atm(i,j)
205  enddo ; enddo
206  else
207  !$OMP parallel do default(shared)
208  do j=jsq,jeq+1 ; do i=isq,ieq+1
209  p(i,j,1) = 0.0 ! or oneatm
210  enddo ; enddo
211  endif
212  !$OMP parallel do default(shared)
213  do j=jsq,jeq+1 ; do k=2,nz+1 ; do i=isq,ieq+1
214  p(i,j,k) = p(i,j,k-1) + gv%H_to_Pa * h(i,j,k-1)
215  enddo ; enddo ; enddo
216 
217  if (use_eos) then
218  ! With a bulk mixed layer, replace the T & S of any layers that are
219  ! lighter than the the buffer layer with the properties of the buffer
220  ! layer. These layers will be massless anyway, and it avoids any
221  ! formal calculations with hydrostatically unstable profiles.
222  if (nkmb>0) then
223  tv_tmp%T => t_tmp ; tv_tmp%S => s_tmp
224  tv_tmp%eqn_of_state => tv%eqn_of_state
225  do i=isq,ieq+1 ; p_ref(i) = tv%P_Ref ; enddo
226  !$OMP parallel do default(shared) private(Rho_cv_BL)
227  do j=jsq,jeq+1
228  do k=1,nkmb ; do i=isq,ieq+1
229  tv_tmp%T(i,j,k) = tv%T(i,j,k) ; tv_tmp%S(i,j,k) = tv%S(i,j,k)
230  enddo ; enddo
231  call calculate_density(tv%T(:,j,nkmb), tv%S(:,j,nkmb), p_ref, &
232  rho_cv_bl(:), isq, ieq-isq+2, tv%eqn_of_state)
233  do k=nkmb+1,nz ; do i=isq,ieq+1
234  if (gv%Rlay(k) < rho_cv_bl(i)) then
235  tv_tmp%T(i,j,k) = tv%T(i,j,nkmb) ; tv_tmp%S(i,j,k) = tv%S(i,j,nkmb)
236  else
237  tv_tmp%T(i,j,k) = tv%T(i,j,k) ; tv_tmp%S(i,j,k) = tv%S(i,j,k)
238  endif
239  enddo ; enddo
240  enddo
241  else
242  tv_tmp%T => tv%T ; tv_tmp%S => tv%S
243  tv_tmp%eqn_of_state => tv%eqn_of_state
244  endif
245  endif
246 
247  ! If regridding is activated, do a linear reconstruction of salinity
248  ! and temperature across each layer. The subscripts 't' and 'b' refer
249  ! to top and bottom values within each layer (these are the only degrees
250  ! of freedeom needed to know the linear profile).
251  if ( use_ale ) then
252  if ( cs%Recon_Scheme == 1 ) then
253  call pressure_gradient_plm(ale_csp, s_t, s_b, t_t, t_b, g, gv, tv, h, cs%boundary_extrap)
254  elseif ( cs%Recon_Scheme == 2) then
255  call pressure_gradient_ppm(ale_csp, s_t, s_b, t_t, t_b, g, gv, tv, h, cs%boundary_extrap)
256  endif
257  endif
258 
259  !$OMP parallel do default(shared) private(alpha_anom,dp)
260  do k=1,nz
261  ! Calculate 4 integrals through the layer that are required in the
262  ! subsequent calculation.
263  if (use_eos) then
264  if ( use_ale ) then
265  if ( cs%Recon_Scheme == 1 ) then
266  call int_spec_vol_dp_generic_plm( t_t(:,:,k), t_b(:,:,k), &
267  s_t(:,:,k), s_b(:,:,k), p(:,:,k), p(:,:,k+1), &
268  alpha_ref, dp_neglect, p(:,:,nz+1), g%HI, &
269  tv%eqn_of_state, dza(:,:,k), intp_dza(:,:,k), &
270  intx_dza(:,:,k), inty_dza(:,:,k), &
271  usemasswghtinterp = cs%useMassWghtInterp)
272  i=k
273  elseif ( cs%Recon_Scheme == 2 ) then
274  call mom_error(fatal, "PressureForce_AFV_nonBouss: "//&
275  "int_spec_vol_dp_generic_ppm does not exist yet.")
276  ! call int_spec_vol_dp_generic_ppm ( tv%T(:,:,k), T_t(:,:,k), T_b(:,:,k), &
277  ! tv%S(:,:,k), S_t(:,:,k), S_b(:,:,k), p(:,:,K), p(:,:,K+1), &
278  ! alpha_ref, G%HI, tv%eqn_of_state, dza(:,:,k), intp_dza(:,:,k), &
279  ! intx_dza(:,:,k), inty_dza(:,:,k))
280  endif
281  else
282  call int_specific_vol_dp(tv_tmp%T(:,:,k), tv_tmp%S(:,:,k), p(:,:,k), &
283  p(:,:,k+1), alpha_ref, g%HI, tv%eqn_of_state, &
284  dza(:,:,k), intp_dza(:,:,k), intx_dza(:,:,k), &
285  inty_dza(:,:,k), bathyp=p(:,:,nz+1), dp_tiny=dp_neglect, &
286  usemasswghtinterp = cs%useMassWghtInterp)
287  endif
288  else
289  alpha_anom = 1.0/gv%Rlay(k) - alpha_ref
290  do j=jsq,jeq+1 ; do i=isq,ieq+1
291  dp(i,j) = gv%H_to_Pa * h(i,j,k)
292  dza(i,j,k) = alpha_anom * dp(i,j)
293  intp_dza(i,j,k) = 0.5 * alpha_anom * dp(i,j)**2
294  enddo ; enddo
295  do j=js,je ; do i=isq,ieq
296  intx_dza(i,j,k) = 0.5 * alpha_anom * (dp(i,j)+dp(i+1,j))
297  enddo ; enddo
298  do j=jsq,jeq ; do i=is,ie
299  inty_dza(i,j,k) = 0.5 * alpha_anom * (dp(i,j)+dp(i,j+1))
300  enddo ; enddo
301  endif
302  enddo
303 
304  ! The bottom geopotential anomaly is calculated first so that the increments
305  ! to the geopotential anomalies can be reused. Alternately, the surface
306  ! geopotential could be calculated directly with separate calls to
307  ! int_specific_vol_dp with alpha_ref=0, and the anomalies used going
308  ! downward, which would relieve the need for dza, intp_dza, intx_dza, and
309  ! inty_dza to be 3-D arrays.
310 
311  ! Sum vertically to determine the surface geopotential anomaly.
312  !$OMP parallel do default(shared)
313  do j=jsq,jeq+1
314  do i=isq,ieq+1
315  za(i,j) = alpha_ref*p(i,j,nz+1) - g_earth_z*g%bathyT(i,j)
316  enddo
317  do k=nz,1,-1 ; do i=isq,ieq+1
318  za(i,j) = za(i,j) + dza(i,j,k)
319  enddo ; enddo
320  enddo
321 
322  if (cs%tides) then
323  ! Find and add the tidal geopotential anomaly.
324  !$OMP parallel do default(shared)
325  do j=jsq,jeq+1 ; do i=isq,ieq+1
326  ssh(i,j) = (za(i,j) - alpha_ref*p(i,j,1)) * i_gearth
327  enddo ; enddo
328  call calc_tidal_forcing(cs%Time, ssh, e_tidal, g, cs%tides_CSp, m_to_z=us%m_to_Z)
329  !$OMP parallel do default(shared)
330  do j=jsq,jeq+1 ; do i=isq,ieq+1
331  za(i,j) = za(i,j) - g_earth_z * e_tidal(i,j)
332  enddo ; enddo
333  endif
334 
335  if (cs%GFS_scale < 1.0) then
336  ! Adjust the Montgomery potential to make this a reduced gravity model.
337  if (use_eos) then
338  !$OMP parallel do default(shared) private(rho_in_situ)
339  do j=jsq,jeq+1
340  call calculate_density(tv_tmp%T(:,j,1), tv_tmp%S(:,j,1), p(:,j,1), &
341  rho_in_situ, isq, ieq-isq+2, tv%eqn_of_state)
342 
343  do i=isq,ieq+1
344  dm(i,j) = (cs%GFS_scale - 1.0) * &
345  (p(i,j,1)*(1.0/rho_in_situ(i) - alpha_ref) + za(i,j))
346  enddo
347  enddo
348  else
349  !$OMP parallel do default(shared)
350  do j=jsq,jeq+1 ; do i=isq,ieq+1
351  dm(i,j) = (cs%GFS_scale - 1.0) * &
352  (p(i,j,1)*(1.0/gv%Rlay(1) - alpha_ref) + za(i,j))
353  enddo ; enddo
354  endif
355 ! else
356 ! do j=Jsq,Jeq+1 ; do i=Isq,Ieq+1 ; dM(i,j) = 0.0 ; enddo ; enddo
357  endif
358 
359  ! This order of integrating upward and then downward again is necessary with
360  ! a nonlinear equation of state, so that the surface geopotentials will go
361  ! linearly between the values at thickness points, but the bottom
362  ! geopotentials will not now be linear at the sub-grid-scale. Doing this
363  ! ensures no motion with flat isopycnals, even with a nonlinear equation of state.
364  !$OMP parallel do default(shared)
365  do j=js,je ; do i=isq,ieq
366  intx_za(i,j) = 0.5*(za(i,j) + za(i+1,j))
367  enddo ; enddo
368  !$OMP parallel do default(shared)
369  do j=jsq,jeq ; do i=is,ie
370  inty_za(i,j) = 0.5*(za(i,j) + za(i,j+1))
371  enddo ; enddo
372  do k=1,nz
373  ! These expressions for the acceleration have been carefully checked in
374  ! a set of idealized cases, and should be bug-free.
375  !$OMP parallel do default(shared)
376  do j=jsq,jeq+1 ; do i=isq,ieq+1
377  dp(i,j) = gv%H_to_Pa*h(i,j,k)
378  za(i,j) = za(i,j) - dza(i,j,k)
379  enddo ; enddo
380  !$OMP parallel do default(shared)
381  do j=js,je ; do i=isq,ieq
382  intx_za(i,j) = intx_za(i,j) - intx_dza(i,j,k)
383  pfu(i,j,k) = (((za(i,j)*dp(i,j) + intp_dza(i,j,k)) - &
384  (za(i+1,j)*dp(i+1,j) + intp_dza(i+1,j,k))) + &
385  ((dp(i+1,j) - dp(i,j)) * intx_za(i,j) - &
386  (p(i+1,j,k) - p(i,j,k)) * intx_dza(i,j,k))) * &
387  (2.0*g%IdxCu(i,j) / ((dp(i,j) + dp(i+1,j)) + &
388  dp_neglect))
389  enddo ; enddo
390  !$OMP parallel do default(shared)
391  do j=jsq,jeq ; do i=is,ie
392  inty_za(i,j) = inty_za(i,j) - inty_dza(i,j,k)
393  pfv(i,j,k) = (((za(i,j)*dp(i,j) + intp_dza(i,j,k)) - &
394  (za(i,j+1)*dp(i,j+1) + intp_dza(i,j+1,k))) + &
395  ((dp(i,j+1) - dp(i,j)) * inty_za(i,j) - &
396  (p(i,j+1,k) - p(i,j,k)) * inty_dza(i,j,k))) * &
397  (2.0*g%IdyCv(i,j) / ((dp(i,j) + dp(i,j+1)) + &
398  dp_neglect))
399  enddo ; enddo
400 
401  if (cs%GFS_scale < 1.0) then
402  ! Adjust the Montgomery potential to make this a reduced gravity model.
403  !$OMP parallel do default(shared)
404  do j=js,je ; do i=isq,ieq
405  pfu(i,j,k) = pfu(i,j,k) - (dm(i+1,j) - dm(i,j)) * g%IdxCu(i,j)
406  enddo ; enddo
407  !$OMP parallel do default(shared)
408  do j=jsq,jeq ; do i=is,ie
409  pfv(i,j,k) = pfv(i,j,k) - (dm(i,j+1) - dm(i,j)) * g%IdyCv(i,j)
410  enddo ; enddo
411  endif
412  enddo
413 
414  if (present(pbce)) then
415  call set_pbce_nonbouss(p, tv_tmp, g, gv, us, cs%GFS_scale, pbce)
416  endif
417 
418  if (present(eta)) then
419  pa_to_h = 1.0 / gv%H_to_Pa
420  if (use_p_atm) then
421  !$OMP parallel do default(shared)
422  do j=jsq,jeq+1 ; do i=isq,ieq+1
423  eta(i,j) = (p(i,j,nz+1) - p_atm(i,j))*pa_to_h ! eta has the same units as h.
424  enddo ; enddo
425  else
426  !$OMP parallel do default(shared)
427  do j=jsq,jeq+1 ; do i=isq,ieq+1
428  eta(i,j) = p(i,j,nz+1)*pa_to_h ! eta has the same units as h.
429  enddo ; enddo
430  endif
431  endif
432 
433  if (cs%id_e_tidal>0) call post_data(cs%id_e_tidal, e_tidal, cs%diag)
434 
435 end subroutine pressureforce_afv_nonbouss
436 
437 !> \brief Boussinesq analytically-integrated finite volume form of pressure gradient
438 !!
439 !! Determines the acceleration due to hydrostatic pressure forces, using
440 !! the finite volume form of the terms and analytic integrals in depth.
441 !!
442 !! To work, the following fields must be set outside of the usual (is:ie,js:je)
443 !! range before this subroutine is called:
444 !! h(isB:ie+1,jsB:je+1), T(isB:ie+1,jsB:je+1), and S(isB:ie+1,jsB:je+1).
445 subroutine pressureforce_afv_bouss(h, tv, PFu, PFv, G, GV, US, CS, ALE_CSp, p_atm, pbce, eta)
446  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
447  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure
448  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
449  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness [H ~> m]
450  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables
451  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(out) :: pfu !< Zonal acceleration [m s-2]
452  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(out) :: pfv !< Meridional acceleration [m s-2]
453  type(pressureforce_afv_cs), pointer :: cs !< Finite volume PGF control structure
454  type(ale_cs), pointer :: ale_csp !< ALE control structure
455  real, dimension(:,:), optional, pointer :: p_atm !< The pressure at the ice-ocean
456  !! or atmosphere-ocean interface [Pa].
457  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), optional, intent(out) :: pbce !< The baroclinic pressure
458  !! anomaly in each layer due to eta anomalies
459  !! [m2 s-2 H-1 ~> m s-2 or m4 s-2 kg-1].
460  real, dimension(SZI_(G),SZJ_(G)), optional, intent(out) :: eta !< The bottom mass used to
461  !! calculate PFu and PFv [H ~> m or kg m-2], with any
462  !! tidal contributions or compressibility compensation.
463  ! Local variables
464  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1) :: e ! Interface height in depth units [Z ~> m].
465  real, dimension(SZI_(G),SZJ_(G)) :: &
466  e_tidal, & ! The bottom geopotential anomaly due to tidal forces from
467  ! astronomical sources and self-attraction and loading [Z ~> m].
468  dm ! The barotropic adjustment to the Montgomery potential to
469  ! account for a reduced gravity model [m2 s-2].
470  real, dimension(SZI_(G)) :: &
471  rho_cv_bl ! The coordinate potential density in the deepest variable
472  ! density near-surface layer [kg m-3].
473  real, dimension(SZI_(G),SZJ_(G)) :: &
474  dz, & ! The change in geopotential thickness through a layer [m2 s-2].
475  pa, & ! The pressure anomaly (i.e. pressure + g*RHO_0*e) at the
476  ! the interface atop a layer [Pa].
477  dpa, & ! The change in pressure anomaly between the top and bottom
478  ! of a layer [Pa].
479  intz_dpa ! The vertical integral in depth of the pressure anomaly less the
480  ! pressure anomaly at the top of the layer [H Pa ~> m Pa or kg m-2 Pa].
481  real, dimension(SZIB_(G),SZJ_(G)) :: &
482  intx_pa, & ! The zonal integral of the pressure anomaly along the interface
483  ! atop a layer, divided by the grid spacing [Pa].
484  intx_dpa ! The change in intx_pa through a layer [Pa].
485  real, dimension(SZI_(G),SZJB_(G)) :: &
486  inty_pa, & ! The meridional integral of the pressure anomaly along the
487  ! interface atop a layer, divided by the grid spacing [Pa].
488  inty_dpa ! The change in inty_pa through a layer [Pa].
489 
490  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), target :: &
491  t_tmp, & ! Temporary array of temperatures where layers that are lighter
492  ! than the mixed layer have the mixed layer's properties [degC].
493  s_tmp ! Temporary array of salinities where layers that are lighter
494  ! than the mixed layer have the mixed layer's properties [ppt].
495  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
496  s_t, s_b, t_t, t_b ! Top and bottom edge values for linear reconstructions
497  ! of salinity and temperature within each layer.
498  real :: rho_in_situ(szi_(g)) ! The in situ density [kg m-3].
499  real :: p_ref(szi_(g)) ! The pressure used to calculate the coordinate
500  ! density, [Pa] (usually 2e7 Pa = 2000 dbar).
501  real :: p0(szi_(g)) ! An array of zeros to use for pressure [Pa].
502  real :: h_neglect ! A thickness that is so small it is usually lost
503  ! in roundoff and can be neglected [H ~> m].
504  real :: g_earth_z ! A scaled version of g_Earth [m2 Z-1 s-2 ~> m s-2].
505  real :: i_rho0 ! 1/Rho0 [m3 kg-1].
506  real :: g_rho0 ! G_Earth / Rho0 in [m5 Z-1 s-2 kg-1 ~> m4 s-2 kg-1].
507  real :: rho_ref ! The reference density [kg m-3].
508  real :: dz_neglect ! A minimal thickness [Z ~> m], like e.
509  logical :: use_p_atm ! If true, use the atmospheric pressure.
510  logical :: use_ale ! If true, use an ALE pressure reconstruction.
511  logical :: use_eos ! If true, density is calculated from T & S using an equation of state.
512  type(thermo_var_ptrs) :: tv_tmp! A structure of temporary T & S.
513 
514  real, parameter :: c1_6 = 1.0/6.0
515  integer :: is, ie, js, je, isq, ieq, jsq, jeq, nz, nkmb
516  integer :: i, j, k
517 
518  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
519  nkmb=gv%nk_rho_varies
520  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
521 
522  if (.not.associated(cs)) call mom_error(fatal, &
523  "MOM_PressureForce_AFV_Bouss: Module must be initialized before it is used.")
524 
525  use_p_atm = .false.
526  if (present(p_atm)) then ; if (associated(p_atm)) use_p_atm = .true. ; endif
527  use_eos = associated(tv%eqn_of_state)
528  do i=isq,ieq+1 ; p0(i) = 0.0 ; enddo
529  use_ale = .false.
530  if (associated(ale_csp)) use_ale = cs%reconstruct .and. use_eos
531 
532  h_neglect = gv%H_subroundoff
533  dz_neglect = gv%H_subroundoff * gv%H_to_Z
534  i_rho0 = 1.0/gv%Rho0
535  g_earth_z = us%L_T_to_m_s**2 * gv%g_Earth
536  g_rho0 = g_earth_z/gv%Rho0
537  rho_ref = cs%Rho0
538 
539  if (cs%tides) then
540  ! Determine the surface height anomaly for calculating self attraction
541  ! and loading. This should really be based on bottom pressure anomalies,
542  ! but that is not yet implemented, and the current form is correct for
543  ! barotropic tides.
544  !$OMP parallel do default(shared)
545  do j=jsq,jeq+1
546  do i=isq,ieq+1
547  e(i,j,1) = -g%bathyT(i,j)
548  enddo
549  do k=1,nz ; do i=isq,ieq+1
550  e(i,j,1) = e(i,j,1) + h(i,j,k)*gv%H_to_Z
551  enddo ; enddo
552  enddo
553  call calc_tidal_forcing(cs%Time, e(:,:,1), e_tidal, g, cs%tides_CSp, m_to_z=us%m_to_Z)
554  endif
555 
556 ! Here layer interface heights, e, are calculated.
557  if (cs%tides) then
558  !$OMP parallel do default(shared)
559  do j=jsq,jeq+1 ; do i=isq,ieq+1
560  e(i,j,nz+1) = -(g%bathyT(i,j) + e_tidal(i,j))
561  enddo ; enddo
562  else
563  !$OMP parallel do default(shared)
564  do j=jsq,jeq+1 ; do i=isq,ieq+1
565  e(i,j,nz+1) = -g%bathyT(i,j)
566  enddo ; enddo
567  endif
568  !$OMP parallel do default(shared)
569  do j=jsq,jeq+1; do k=nz,1,-1 ; do i=isq,ieq+1
570  e(i,j,k) = e(i,j,k+1) + h(i,j,k)*gv%H_to_Z
571  enddo ; enddo ; enddo
572 
573  if (use_eos) then
574 ! With a bulk mixed layer, replace the T & S of any layers that are
575 ! lighter than the the buffer layer with the properties of the buffer
576 ! layer. These layers will be massless anyway, and it avoids any
577 ! formal calculations with hydrostatically unstable profiles.
578 
579  if (nkmb>0) then
580  tv_tmp%T => t_tmp ; tv_tmp%S => s_tmp
581  tv_tmp%eqn_of_state => tv%eqn_of_state
582 
583  do i=isq,ieq+1 ; p_ref(i) = tv%P_Ref ; enddo
584  !$OMP parallel do default(shared) private(Rho_cv_BL)
585  do j=jsq,jeq+1
586  do k=1,nkmb ; do i=isq,ieq+1
587  tv_tmp%T(i,j,k) = tv%T(i,j,k) ; tv_tmp%S(i,j,k) = tv%S(i,j,k)
588  enddo ; enddo
589  call calculate_density(tv%T(:,j,nkmb), tv%S(:,j,nkmb), p_ref, &
590  rho_cv_bl(:), isq, ieq-isq+2, tv%eqn_of_state)
591 
592  do k=nkmb+1,nz ; do i=isq,ieq+1
593  if (gv%Rlay(k) < rho_cv_bl(i)) then
594  tv_tmp%T(i,j,k) = tv%T(i,j,nkmb) ; tv_tmp%S(i,j,k) = tv%S(i,j,nkmb)
595  else
596  tv_tmp%T(i,j,k) = tv%T(i,j,k) ; tv_tmp%S(i,j,k) = tv%S(i,j,k)
597  endif
598  enddo ; enddo
599  enddo
600  else
601  tv_tmp%T => tv%T ; tv_tmp%S => tv%S
602  tv_tmp%eqn_of_state => tv%eqn_of_state
603  endif
604  endif
605 
606  if (cs%GFS_scale < 1.0) then
607  ! Adjust the Montgomery potential to make this a reduced gravity model.
608  if (use_eos) then
609  !$OMP parallel do default(shared)
610  do j=jsq,jeq+1
611  if (use_p_atm) then
612  call calculate_density(tv_tmp%T(:,j,1), tv_tmp%S(:,j,1), p_atm(:,j), &
613  rho_in_situ, isq, ieq-isq+2, tv%eqn_of_state)
614  else
615  call calculate_density(tv_tmp%T(:,j,1), tv_tmp%S(:,j,1), p0, &
616  rho_in_situ, isq, ieq-isq+2, tv%eqn_of_state)
617  endif
618  do i=isq,ieq+1
619  dm(i,j) = (cs%GFS_scale - 1.0) * (g_rho0 * rho_in_situ(i)) * e(i,j,1)
620  enddo
621  enddo
622  else
623  !$OMP parallel do default(shared)
624  do j=jsq,jeq+1 ; do i=isq,ieq+1
625  dm(i,j) = (cs%GFS_scale - 1.0) * (g_rho0 * gv%Rlay(1)) * e(i,j,1)
626  enddo ; enddo
627  endif
628  endif
629  ! I have checked that rho_0 drops out and that the 1-layer case is right. RWH.
630 
631  ! If regridding is activated, do a linear reconstruction of salinity
632  ! and temperature across each layer. The subscripts 't' and 'b' refer
633  ! to top and bottom values within each layer (these are the only degrees
634  ! of freedeom needed to know the linear profile).
635  if ( use_ale ) then
636  if ( cs%Recon_Scheme == 1 ) then
637  call pressure_gradient_plm(ale_csp, s_t, s_b, t_t, t_b, g, gv, tv, h, cs%boundary_extrap)
638  elseif ( cs%Recon_Scheme == 2 ) then
639  call pressure_gradient_ppm(ale_csp, s_t, s_b, t_t, t_b, g, gv, tv, h, cs%boundary_extrap)
640  endif
641  endif
642 
643  ! Set the surface boundary conditions on pressure anomaly and its horizontal
644  ! integrals, assuming that the surface pressure anomaly varies linearly
645  ! in x and y.
646  if (use_p_atm) then
647  !$OMP parallel do default(shared)
648  do j=jsq,jeq+1 ; do i=isq,ieq+1
649  pa(i,j) = (rho_ref*g_earth_z)*e(i,j,1) + p_atm(i,j)
650  enddo ; enddo
651  else
652  !$OMP parallel do default(shared)
653  do j=jsq,jeq+1 ; do i=isq,ieq+1
654  pa(i,j) = (rho_ref*g_earth_z)*e(i,j,1)
655  enddo ; enddo
656  endif
657  !$OMP parallel do default(shared)
658  do j=js,je ; do i=isq,ieq
659  intx_pa(i,j) = 0.5*(pa(i,j) + pa(i+1,j))
660  enddo ; enddo
661  !$OMP parallel do default(shared)
662  do j=jsq,jeq ; do i=is,ie
663  inty_pa(i,j) = 0.5*(pa(i,j) + pa(i,j+1))
664  enddo ; enddo
665 
666  do k=1,nz
667  ! Calculate 4 integrals through the layer that are required in the
668  ! subsequent calculation.
669 
670  if (use_eos) then
671  ! The following routine computes the integrals that are needed to
672  ! calculate the pressure gradient force. Linear profiles for T and S are
673  ! assumed when regridding is activated. Otherwise, the previous version
674  ! is used, whereby densities within each layer are constant no matter
675  ! where the layers are located.
676  if ( use_ale ) then
677  if ( cs%Recon_Scheme == 1 ) then
678  call int_density_dz_generic_plm( t_t(:,:,k), t_b(:,:,k), &
679  s_t(:,:,k), s_b(:,:,k), e(:,:,k), e(:,:,k+1), &
680  rho_ref, cs%Rho0, g_earth_z, &
681  dz_neglect, g%bathyT, g%HI, g%HI, &
682  tv%eqn_of_state, dpa, intz_dpa, intx_dpa, inty_dpa, &
683  usemasswghtinterp = cs%useMassWghtInterp)
684  elseif ( cs%Recon_Scheme == 2 ) then
685  call int_density_dz_generic_ppm( tv%T(:,:,k), t_t(:,:,k), t_b(:,:,k), &
686  tv%S(:,:,k), s_t(:,:,k), s_b(:,:,k), e(:,:,k), e(:,:,k+1), &
687  rho_ref, cs%Rho0, g_earth_z, &
688  g%HI, g%HI, tv%eqn_of_state, dpa, intz_dpa, &
689  intx_dpa, inty_dpa)
690  endif
691  else
692  call int_density_dz(tv_tmp%T(:,:,k), tv_tmp%S(:,:,k), e(:,:,k), e(:,:,k+1), &
693  rho_ref, cs%Rho0, g_earth_z, g%HI, g%HI, tv%eqn_of_state, &
694  dpa, intz_dpa, intx_dpa, inty_dpa, &
695  g%bathyT, dz_neglect, cs%useMassWghtInterp)
696  endif
697  !$OMP parallel do default(shared)
698  do j=jsq,jeq+1 ; do i=isq,ieq+1
699  intz_dpa(i,j) = intz_dpa(i,j)*gv%Z_to_H
700  enddo ; enddo
701  else
702  !$OMP parallel do default(shared)
703  do j=jsq,jeq+1 ; do i=isq,ieq+1
704  dz(i,j) = g_earth_z * gv%H_to_Z*h(i,j,k)
705  dpa(i,j) = (gv%Rlay(k) - rho_ref)*dz(i,j)
706  intz_dpa(i,j) = 0.5*(gv%Rlay(k) - rho_ref)*dz(i,j)*h(i,j,k)
707  enddo ; enddo
708  !$OMP parallel do default(shared)
709  do j=js,je ; do i=isq,ieq
710  intx_dpa(i,j) = 0.5*(gv%Rlay(k) - rho_ref) * (dz(i,j)+dz(i+1,j))
711  enddo ; enddo
712  !$OMP parallel do default(shared)
713  do j=jsq,jeq ; do i=is,ie
714  inty_dpa(i,j) = 0.5*(gv%Rlay(k) - rho_ref) * (dz(i,j)+dz(i,j+1))
715  enddo ; enddo
716  endif
717 
718  ! Compute pressure gradient in x direction
719  !$OMP parallel do default(shared)
720  do j=js,je ; do i=isq,ieq
721  pfu(i,j,k) = (((pa(i,j)*h(i,j,k) + intz_dpa(i,j)) - &
722  (pa(i+1,j)*h(i+1,j,k) + intz_dpa(i+1,j))) + &
723  ((h(i+1,j,k) - h(i,j,k)) * intx_pa(i,j) - &
724  (e(i+1,j,k+1) - e(i,j,k+1)) * intx_dpa(i,j) * gv%Z_to_H)) * &
725  ((2.0*i_rho0*g%IdxCu(i,j)) / &
726  ((h(i,j,k) + h(i+1,j,k)) + h_neglect))
727  intx_pa(i,j) = intx_pa(i,j) + intx_dpa(i,j)
728  enddo ; enddo
729  ! Compute pressure gradient in y direction
730  !$OMP parallel do default(shared)
731  do j=jsq,jeq ; do i=is,ie
732  pfv(i,j,k) = (((pa(i,j)*h(i,j,k) + intz_dpa(i,j)) - &
733  (pa(i,j+1)*h(i,j+1,k) + intz_dpa(i,j+1))) + &
734  ((h(i,j+1,k) - h(i,j,k)) * inty_pa(i,j) - &
735  (e(i,j+1,k+1) - e(i,j,k+1)) * inty_dpa(i,j) * gv%Z_to_H)) * &
736  ((2.0*i_rho0*g%IdyCv(i,j)) / &
737  ((h(i,j,k) + h(i,j+1,k)) + h_neglect))
738  inty_pa(i,j) = inty_pa(i,j) + inty_dpa(i,j)
739  enddo ; enddo
740  !$OMP parallel do default(shared)
741  do j=jsq,jeq+1 ; do i=isq,ieq+1
742  pa(i,j) = pa(i,j) + dpa(i,j)
743  enddo ; enddo
744  enddo
745 
746  if (cs%GFS_scale < 1.0) then
747  do k=1,nz
748  !$OMP parallel do default(shared)
749  do j=js,je ; do i=isq,ieq
750  pfu(i,j,k) = pfu(i,j,k) - (dm(i+1,j) - dm(i,j)) * g%IdxCu(i,j)
751  enddo ; enddo
752  !$OMP parallel do default(shared)
753  do j=jsq,jeq ; do i=is,ie
754  pfv(i,j,k) = pfv(i,j,k) - (dm(i,j+1) - dm(i,j)) * g%IdyCv(i,j)
755  enddo ; enddo
756  enddo
757  endif
758 
759  if (present(pbce)) then
760  call set_pbce_bouss(e, tv_tmp, g, gv, us, cs%Rho0, cs%GFS_scale, pbce)
761  endif
762 
763  if (present(eta)) then
764  if (cs%tides) then
765  ! eta is the sea surface height relative to a time-invariant geoid, for
766  ! comparison with what is used for eta in btstep. See how e was calculated
767  ! about 200 lines above.
768  !$OMP parallel do default(shared)
769  do j=jsq,jeq+1 ; do i=isq,ieq+1
770  eta(i,j) = e(i,j,1)*gv%Z_to_H + e_tidal(i,j)*gv%Z_to_H
771  enddo ; enddo
772  else
773  !$OMP parallel do default(shared)
774  do j=jsq,jeq+1 ; do i=isq,ieq+1
775  eta(i,j) = e(i,j,1)*gv%Z_to_H
776  enddo ; enddo
777  endif
778  endif
779 
780  if (cs%id_e_tidal>0) call post_data(cs%id_e_tidal, e_tidal, cs%diag)
781 
782 end subroutine pressureforce_afv_bouss
783 
784 !> Initializes the finite volume pressure gradient control structure
785 subroutine pressureforce_afv_init(Time, G, GV, US, param_file, diag, CS, tides_CSp)
786  type(time_type), target, intent(in) :: time !< Current model time
787  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
788  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure
789  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
790  type(param_file_type), intent(in) :: param_file !< Parameter file handles
791  type(diag_ctrl), target, intent(inout) :: diag !< Diagnostics control structure
792  type(pressureforce_afv_cs), pointer :: cs !< Finite volume PGF control structure
793  type(tidal_forcing_cs), optional, pointer :: tides_csp !< Tides control structure
794 ! This include declares and sets the variable "version".
795 #include "version_variable.h"
796  character(len=40) :: mdl ! This module's name.
797  logical :: use_ale
798 
799  if (associated(cs)) then
800  call mom_error(warning, "PressureForce_init called with an associated "// &
801  "control structure.")
802  return
803  else ; allocate(cs) ; endif
804 
805  cs%diag => diag ; cs%Time => time
806  if (present(tides_csp)) then
807  if (associated(tides_csp)) cs%tides_CSp => tides_csp
808  endif
809 
810  mdl = "MOM_PressureForce_AFV"
811  call log_version(param_file, mdl, version, "")
812  call get_param(param_file, mdl, "RHO_0", cs%Rho0, &
813  "The mean ocean density used with BOUSSINESQ true to "//&
814  "calculate accelerations and the mass for conservation "//&
815  "properties, or with BOUSSINSEQ false to convert some "//&
816  "parameters from vertical units of m to kg m-2.", &
817  units="kg m-3", default=1035.0)
818  call get_param(param_file, mdl, "TIDES", cs%tides, &
819  "If true, apply tidal momentum forcing.", default=.false.)
820  call get_param(param_file, "MOM", "USE_REGRIDDING", use_ale, &
821  "If True, use the ALE algorithm (regridding/remapping). "//&
822  "If False, use the layered isopycnal algorithm.", default=.false. )
823  call get_param(param_file, mdl, "MASS_WEIGHT_IN_PRESSURE_GRADIENT", cs%useMassWghtInterp, &
824  "If true, use mass weighting when interpolating T/S for "//&
825  "integrals near the bathymetry in AFV pressure gradient "//&
826  "calculations.", default=.false.)
827  call get_param(param_file, mdl, "RECONSTRUCT_FOR_PRESSURE", cs%reconstruct, &
828  "If True, use vertical reconstruction of T & S within "//&
829  "the integrals of the FV pressure gradient calculation. "//&
830  "If False, use the constant-by-layer algorithm. "//&
831  "The default is set by USE_REGRIDDING.", &
832  default=use_ale )
833  call get_param(param_file, mdl, "PRESSURE_RECONSTRUCTION_SCHEME", cs%Recon_Scheme, &
834  "Order of vertical reconstruction of T/S to use in the "//&
835  "integrals within the FV pressure gradient calculation.\n"//&
836  " 0: PCM or no reconstruction.\n"//&
837  " 1: PLM reconstruction.\n"//&
838  " 2: PPM reconstruction.", default=1)
839  call get_param(param_file, mdl, "BOUNDARY_EXTRAPOLATION_PRESSURE", cs%boundary_extrap, &
840  "If true, the reconstruction of T & S for pressure in "//&
841  "boundary cells is extrapolated, rather than using PCM "//&
842  "in these cells. If true, the same order polynomial is "//&
843  "used as is used for the interior cells.", default=.true.)
844 
845  if (cs%tides) then
846  cs%id_e_tidal = register_diag_field('ocean_model', 'e_tidal', diag%axesT1, &
847  time, 'Tidal Forcing Astronomical and SAL Height Anomaly', 'meter', conversion=us%Z_to_m)
848  endif
849 
850  cs%GFS_scale = 1.0
851  if (gv%g_prime(1) /= gv%g_Earth) cs%GFS_scale = gv%g_prime(1) / gv%g_Earth
852 
853  call log_param(param_file, mdl, "GFS / G_EARTH", cs%GFS_scale)
854 
855 end subroutine pressureforce_afv_init
856 
857 !> Deallocates the finite volume pressure gradient control structure
858 subroutine pressureforce_afv_end(CS)
859  type(pressureforce_afv_cs), pointer :: cs !< Finite volume pressure control structure that
860  !! will be deallocated in this subroutine.
861  if (associated(cs)) deallocate(cs)
862 end subroutine pressureforce_afv_end
863 
864 !> \namespace mom_pressureforce_afv
865 !!
866 !! Provides the Boussinesq and non-Boussinesq forms of horizontal accelerations
867 !! due to pressure gradients using a 2nd-order analytically vertically integrated
868 !! finite volume form, as described by Adcroft et al., 2008.
869 !!
870 !! This form eliminates the thermobaric instabilities that had been a problem with
871 !! previous forms of the pressure gradient force calculation, as described by
872 !! Hallberg, 2005.
873 !!
874 !! Adcroft, A., R. Hallberg, and M. Harrison, 2008: A finite volume discretization
875 !! of the pressure gradient force using analytic integration. Ocean Modelling, 22,
876 !! 106-113. http://doi.org/10.1016/j.ocemod.2008.02.001
877 !!
878 !! Hallberg, 2005: A thermobaric instability of Lagrangian vertical coordinate
879 !! ocean models. Ocean Modelling, 8, 279-300.
880 !! http://dx.doi.org/10.1016/j.ocemod.2004.01.001
881 
882 end module mom_pressureforce_afv
mom_verticalgrid
Provides a transparent vertical ocean grid type and supporting routines.
Definition: MOM_verticalGrid.F90:2
mom_file_parser::log_version
An overloaded interface to log version information about modules.
Definition: MOM_file_parser.F90:109
mom_diag_mediator
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Definition: MOM_diag_mediator.F90:3
mom_variables::thermo_var_ptrs
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Definition: MOM_variables.F90:82
mom_eos
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
mom_file_parser::param_file_type
A structure that can be parsed to read and document run-time parameters.
Definition: MOM_file_parser.F90:54
mom_file_parser::get_param
An overloaded interface to read and log the values of various types of parameters.
Definition: MOM_file_parser.F90:102
mom_unit_scaling::unit_scale_type
Describes various unit conversion factors.
Definition: MOM_unit_scaling.F90:14
mom_diag_mediator::post_data
Make a diagnostic available for averaging or output.
Definition: MOM_diag_mediator.F90:70
mom_tidal_forcing
Tidal contributions to geopotential.
Definition: MOM_tidal_forcing.F90:2
mom_tidal_forcing::tidal_forcing_cs
The control structure for the MOM_tidal_forcing module.
Definition: MOM_tidal_forcing.F90:26
mom_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_pressureforce_afv::pressureforce_afv_cs
Finite volume pressure gradient control structure.
Definition: MOM_PressureForce_analytic_FV.F90:36
mom_ale
This module contains the main regridding routines.
Definition: MOM_ALE.F90:9
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_ale::ale_cs
ALE control structure.
Definition: MOM_ALE.F90:63
mom_pressureforce_afv
Analytically integrated finite volume pressure gradient.
Definition: MOM_PressureForce_analytic_FV.F90:2
mom_pressureforce_mont
Provides the Montgomery potential form of pressure gradient.
Definition: MOM_PressureForce_Montgomery.F90:2
mom_eos::calculate_density_derivs
Calculate the derivatives of density with temperature and salinity from T, S, and P.
Definition: MOM_EOS.F90:70
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_unit_scaling
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Definition: MOM_unit_scaling.F90:2
mom_file_parser::log_param
An overloaded interface to log the values of various types of parameters.
Definition: MOM_file_parser.F90:96
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:25
mom_diag_mediator::diag_ctrl
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Definition: MOM_diag_mediator.F90:239
mom_eos::calculate_density
Calculates density of sea water from T, S and P.
Definition: MOM_EOS.F90:60