MOM6
mom_pressureforce_afv Module Reference

Detailed Description

Analytically integrated finite volume pressure gradient.

Provides the Boussinesq and non-Boussinesq forms of horizontal accelerations due to pressure gradients using a 2nd-order analytically vertically integrated finite volume form, as described by Adcroft et al., 2008.

This form eliminates the thermobaric instabilities that had been a problem with previous forms of the pressure gradient force calculation, as described by Hallberg, 2005.

Adcroft, A., R. Hallberg, and M. Harrison, 2008: A finite volume discretization of the pressure gradient force using analytic integration. Ocean Modelling, 22, 106-113. http://doi.org/10.1016/j.ocemod.2008.02.001

Hallberg, 2005: A thermobaric instability of Lagrangian vertical coordinate ocean models. Ocean Modelling, 8, 279-300. http://dx.doi.org/10.1016/j.ocemod.2004.01.001

Data Types

type  pressureforce_afv_cs
 Finite volume pressure gradient control structure. More...
 

Functions/Subroutines

subroutine, public pressureforce_afv (h, tv, PFu, PFv, G, GV, CS, ALE_CSp, p_atm, pbce, eta)
 Thin interface between the model and the Boussinesq and non-Boussinesq pressure force routines. More...
 
subroutine, public pressureforce_afv_nonbouss (h, tv, PFu, PFv, G, GV, CS, p_atm, pbce, eta)
 Non-Boussinesq analytically-integrated finite volume form of pressure gradient. More...
 
subroutine, public pressureforce_afv_bouss (h, tv, PFu, PFv, G, GV, CS, ALE_CSp, p_atm, pbce, eta)
 Boussinesq analytically-integrated finite volume form of pressure gradient. More...
 
subroutine, public pressureforce_afv_init (Time, G, GV, param_file, diag, CS, tides_CSp)
 Initializes the finite volume pressure gradient control structure. More...
 
subroutine, public pressureforce_afv_end (CS)
 Deallocates the finite volume pressure gradient control structure. More...
 

Function/Subroutine Documentation

◆ pressureforce_afv()

subroutine, public mom_pressureforce_afv::pressureforce_afv ( real, dimension(szi_(g),szj_(g),szk_(g)), intent(in)  h,
type(thermo_var_ptrs), intent(inout)  tv,
real, dimension(szib_(g),szj_(g),szk_(g)), intent(out)  PFu,
real, dimension(szi_(g),szjb_(g),szk_(g)), intent(out)  PFv,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
type(pressureforce_afv_cs), pointer  CS,
type(ale_cs), pointer  ALE_CSp,
real, dimension(:,:), optional, pointer  p_atm,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(out), optional  pbce,
real, dimension(szi_(g),szj_(g)), intent(out), optional  eta 
)

Thin interface between the model and the Boussinesq and non-Boussinesq pressure force routines.

Parameters
[in]gOcean grid structure
[in]gvVertical grid structure
[in]hLayer thickness (m or kg/m2)
[in,out]tvThermodynamic variables
[out]pfuZonal acceleration (m/s2)
[out]pfvMeridional acceleration (m/s2)
csFinite volume PGF control structure
ale_cspALE control structure
p_atmThe pressure at the ice-ocean or atmosphere-ocean interface in Pa.
[out]pbceThe baroclinic pressure anomaly in each layer due to eta anomalies, in m2 s-2 H-1.
[out]etaThe bottom mass used to calculate PFu and PFv, in H, with any tidal contributions or compressibility compensation.

Definition at line 51 of file MOM_PressureForce_analytic_FV.F90.

References pressureforce_afv_bouss(), and pressureforce_afv_nonbouss().

51  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
52  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure
53  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness (m or kg/m2)
54  type(thermo_var_ptrs), intent(inout) :: tv !< Thermodynamic variables
55  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(out) :: pfu !< Zonal acceleration (m/s2)
56  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(out) :: pfv !< Meridional acceleration (m/s2)
57  type(pressureforce_afv_cs), pointer :: cs !< Finite volume PGF control structure
58  type(ale_cs), pointer :: ale_csp !< ALE control structure
59  real, dimension(:,:), optional, pointer :: p_atm !< The pressure at the ice-ocean
60  !! or atmosphere-ocean interface in Pa.
61  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), optional, intent(out) :: pbce !< The baroclinic pressure
62  !! anomaly in each layer due to eta anomalies,
63  !! in m2 s-2 H-1.
64  real, dimension(SZI_(G),SZJ_(G)), optional, intent(out) :: eta !< The bottom mass used to
65  !! calculate PFu and PFv, in H, with any tidal
66  !! contributions or compressibility compensation.
67 
68  if (gv%Boussinesq) then
69  call pressureforce_afv_bouss(h, tv, pfu, pfv, g, gv, cs, ale_csp, p_atm, pbce, eta)
70  else
71  call pressureforce_afv_nonbouss(h, tv, pfu, pfv, g, gv, cs, p_atm, pbce, eta)
72  endif
73 
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
Here is the call graph for this function:

◆ pressureforce_afv_bouss()

subroutine, public mom_pressureforce_afv::pressureforce_afv_bouss ( real, dimension(szi_(g),szj_(g),szk_(g)), intent(in)  h,
type(thermo_var_ptrs), intent(in)  tv,
real, dimension(szib_(g),szj_(g),szk_(g)), intent(out)  PFu,
real, dimension(szi_(g),szjb_(g),szk_(g)), intent(out)  PFv,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
type(pressureforce_afv_cs), pointer  CS,
type(ale_cs), pointer  ALE_CSp,
real, dimension(:,:), optional, pointer  p_atm,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(out), optional  pbce,
real, dimension(szi_(g),szj_(g)), intent(out), optional  eta 
)

Boussinesq analytically-integrated finite volume form of pressure gradient.

Determines the acceleration due to hydrostatic pressure forces, using the finite volume form of the terms and analytic integrals in depth.

To work, the following fields must be set outside of the usual ie to ie, je to je range before this subroutine is called: h[ie+1] and h[je+1] and (if tveqn_of_state is set) T[ie+1], S[ie+1], T[je+1], and S[je+1].

Parameters
[in]gOcean grid structure
[in]gvVertical grid structure
[in]hLayer thickness (kg/m2)
[in]tvThermodynamic variables
[out]pfuZonal acceleration (m/s2)
[out]pfvMeridional acceleration (m/s2)
csFinite volume PGF control structure
ale_cspALE control structure
p_atmThe pressure at the ice-ocean or atmosphere-ocean interface in Pa.
[out]pbceThe baroclinic pressure anomaly in each layer due to eta anomalies, in m2 s-2 H-1.
[out]etaThe bottom mass used to calculate PFu and PFv, in H, with any tidal contributions or compressibility compensation.

Definition at line 414 of file MOM_PressureForce_analytic_FV.F90.

References mom_tidal_forcing::calc_tidal_forcing(), mom_error_handler::mom_error(), regrid_defs::pressure_reconstruction_plm, regrid_defs::pressure_reconstruction_ppm, and mom_pressureforce_mont::set_pbce_bouss().

Referenced by pressureforce_afv().

414  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
415  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure
416  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness (kg/m2)
417  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables
418  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(out) :: pfu !< Zonal acceleration (m/s2)
419  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(out) :: pfv !< Meridional acceleration (m/s2)
420  type(pressureforce_afv_cs), pointer :: cs !< Finite volume PGF control structure
421  type(ale_cs), pointer :: ale_csp !< ALE control structure
422  real, dimension(:,:), optional, pointer :: p_atm !< The pressure at the ice-ocean
423  !! or atmosphere-ocean interface in Pa.
424  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), optional, intent(out) :: pbce !< The baroclinic pressure
425  !! anomaly in each layer due to eta anomalies,
426  !! in m2 s-2 H-1.
427  real, dimension(SZI_(G),SZJ_(G)), optional, intent(out) :: eta !< The bottom mass used to
428  !! calculate PFu and PFv, in H, with any tidal
429  !! contributions or compressibility compensation.
430  ! Local variables
431  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1) :: e ! Interface height in m.
432  real, dimension(SZI_(G),SZJ_(G)) :: &
433  e_tidal, & ! The bottom geopotential anomaly due to tidal forces from
434  ! astronomical sources and self-attraction and loading, in m.
435  dm ! The barotropic adjustment to the Montgomery potential to
436  ! account for a reduced gravity model, in m2 s-2.
437  real, dimension(SZI_(G)) :: &
438  rho_cv_bl ! The coordinate potential density in the deepest variable
439  ! density near-surface layer, in kg m-3.
440  real, dimension(SZDI_(G%Block(1)),SZDJ_(G%Block(1))) :: & ! on block indices
441  dz_bk, & ! The change in geopotential thickness through a layer, m2 s-2.
442  pa_bk, & ! The pressure anomaly (i.e. pressure + g*RHO_0*e) at the
443  ! the interface atop a layer, in Pa.
444  dpa_bk, & ! The change in pressure anomaly between the top and bottom
445  ! of a layer, in Pa.
446  intz_dpa_bk ! The vertical integral in depth of the pressure anomaly less
447  ! the pressure anomaly at the top of the layer, in H Pa (m Pa).
448  real, dimension(SZDIB_(G%Block(1)),SZDJ_(G%Block(1))) :: & ! on block indices
449  intx_pa_bk, & ! The zonal integral of the pressure anomaly along the interface
450  ! atop a layer, divided by the grid spacing, in Pa.
451  intx_dpa_bk ! The change in intx_pa through a layer, in Pa.
452  real, dimension(SZDI_(G%Block(1)),SZDJB_(G%Block(1))) :: & ! on block indices
453  inty_pa_bk, & ! The meridional integral of the pressure anomaly along the
454  ! interface atop a layer, divided by the grid spacing, in Pa.
455  inty_dpa_bk ! The change in inty_pa through a layer, in Pa.
456 
457  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), target :: &
458  t_tmp, & ! Temporary array of temperatures where layers that are lighter
459  ! than the mixed layer have the mixed layer's properties, in C.
460  s_tmp ! Temporary array of salinities where layers that are lighter
461  ! than the mixed layer have the mixed layer's properties, in psu.
462  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
463  s_t, s_b, t_t, t_b ! Top and bottom edge values for linear reconstructions
464  ! of salinity and temperature within each layer.
465  real :: rho_in_situ(szi_(g)) ! The in situ density, in kg m-3.
466  real :: p_ref(szi_(g)) ! The pressure used to calculate the coordinate
467  ! density, in Pa (usually 2e7 Pa = 2000 dbar).
468  real :: p0(szi_(g)) ! An array of zeros to use for pressure in Pa.
469  real :: h_neglect ! A thickness that is so small it is usually lost
470  ! in roundoff and can be neglected, in m.
471  real :: i_rho0 ! 1/Rho0.
472  real :: g_rho0 ! G_Earth / Rho0 in m4 s-2 kg-1.
473  real :: rho_ref ! The reference density in kg m-3.
474  logical :: use_p_atm ! If true, use the atmospheric pressure.
475  logical :: use_ale ! If true, use an ALE pressure reconstruction.
476  logical :: use_eos ! If true, density is calculated from T & S using an
477  ! equation of state.
478  type(thermo_var_ptrs) :: tv_tmp! A structure of temporary T & S.
479 
480  real, parameter :: c1_6 = 1.0/6.0
481  integer :: is, ie, js, je, isq, ieq, jsq, jeq, nz, nkmb
482  integer :: is_bk, ie_bk, js_bk, je_bk, isq_bk, ieq_bk, jsq_bk, jeq_bk
483  integer :: ioff_bk, joff_bk
484  integer :: i, j, k, n, ib, jb
485  integer :: prscheme
486 
487  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
488  nkmb=gv%nk_rho_varies
489  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
490 
491  if (.not.associated(cs)) call mom_error(fatal, &
492  "MOM_PressureForce: Module must be initialized before it is used.")
493 
494  use_p_atm = .false.
495  if (present(p_atm)) then ; if (associated(p_atm)) use_p_atm = .true. ; endif
496  use_eos = associated(tv%eqn_of_state)
497  do i=isq,ieq+1 ; p0(i) = 0.0 ; enddo
498  use_ale = .false.
499  if (associated(ale_csp)) use_ale = usepressurereconstruction(ale_csp) .and. use_eos
500 
501  prscheme = pressurereconstructionscheme(ale_csp)
502  h_neglect = gv%H_subroundoff
503  i_rho0 = 1.0/gv%Rho0
504  g_rho0 = gv%g_Earth/gv%Rho0
505  rho_ref = cs%Rho0
506 
507  if (cs%tides) then
508  ! Determine the surface height anomaly for calculating self attraction
509  ! and loading. This should really be based on bottom pressure anomalies,
510  ! but that is not yet implemented, and the current form is correct for
511  ! barotropic tides.
512 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,nz,e,G,GV,h)
513  do j=jsq,jeq+1
514  do i=isq,ieq+1
515  e(i,j,1) = -1.0*g%bathyT(i,j)
516  enddo
517  do k=1,nz ; do i=isq,ieq+1
518  e(i,j,1) = e(i,j,1) + h(i,j,k)*gv%H_to_m
519  enddo ; enddo
520  enddo
521  call calc_tidal_forcing(cs%Time, e(:,:,1), e_tidal, g, cs%tides_CSp)
522  endif
523 
524 ! Here layer interface heights, e, are calculated.
525 !$OMP parallel default(none) shared(Isq,Ieq,Jsq,Jeq,nz,e,G,GV,h,CS,e_tidal)
526  if (cs%tides) then
527 !$OMP do
528  do j=jsq,jeq+1 ; do i=isq,ieq+1
529  e(i,j,nz+1) = -1.0*g%bathyT(i,j) - e_tidal(i,j)
530  enddo ; enddo
531  else
532 !$OM do
533  do j=jsq,jeq+1 ; do i=isq,ieq+1
534  e(i,j,nz+1) = -1.0*g%bathyT(i,j)
535  enddo ; enddo
536  endif
537 !$OMP do
538  do j=jsq,jeq+1; do k=nz,1,-1 ; do i=isq,ieq+1
539  e(i,j,k) = e(i,j,k+1) + h(i,j,k)*gv%H_to_m
540  enddo ; enddo ; enddo
541 !$OMP end parallel
542 
543 
544  if (use_eos) then
545 ! With a bulk mixed layer, replace the T & S of any layers that are
546 ! lighter than the the buffer layer with the properties of the buffer
547 ! layer. These layers will be massless anyway, and it avoids any
548 ! formal calculations with hydrostatically unstable profiles.
549 
550  if (nkmb>0) then
551  tv_tmp%T => t_tmp ; tv_tmp%S => s_tmp
552  tv_tmp%eqn_of_state => tv%eqn_of_state
553 
554  do i=isq,ieq+1 ; p_ref(i) = tv%P_Ref ; enddo
555 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,nkmb,nz,GV,tv_tmp,tv,p_ref) &
556 !$OMP private(Rho_cv_BL)
557  do j=jsq,jeq+1
558  do k=1,nkmb ; do i=isq,ieq+1
559  tv_tmp%T(i,j,k) = tv%T(i,j,k) ; tv_tmp%S(i,j,k) = tv%S(i,j,k)
560  enddo ; enddo
561  call calculate_density(tv%T(:,j,nkmb), tv%S(:,j,nkmb), p_ref, &
562  rho_cv_bl(:), isq, ieq-isq+2, tv%eqn_of_state)
563 
564  do k=nkmb+1,nz ; do i=isq,ieq+1
565  if (gv%Rlay(k) < rho_cv_bl(i)) then
566  tv_tmp%T(i,j,k) = tv%T(i,j,nkmb) ; tv_tmp%S(i,j,k) = tv%S(i,j,nkmb)
567  else
568  tv_tmp%T(i,j,k) = tv%T(i,j,k) ; tv_tmp%S(i,j,k) = tv%S(i,j,k)
569  endif
570  enddo ; enddo
571  enddo
572  else
573  tv_tmp%T => tv%T ; tv_tmp%S => tv%S
574  tv_tmp%eqn_of_state => tv%eqn_of_state
575  endif
576  endif
577 
578 !$OMP parallel default(none) shared(Jsq,Jeq,Isq,Ieq,tv_tmp,p_atm,rho_in_situ,tv, &
579 !$OMP p0,dM,CS,G_Rho0,e,use_p_atm,use_EOS,GV, &
580 !$OMP rho_ref,js,je,is,ie)
581  if (cs%GFS_scale < 1.0) then
582  ! Adjust the Montgomery potential to make this a reduced gravity model.
583  if (use_eos) then
584 !$OMP do
585  do j=jsq,jeq+1
586  if (use_p_atm) then
587  call calculate_density(tv_tmp%T(:,j,1), tv_tmp%S(:,j,1), p_atm(:,j), &
588  rho_in_situ, isq, ieq-isq+2, tv%eqn_of_state)
589  else
590  call calculate_density(tv_tmp%T(:,j,1), tv_tmp%S(:,j,1), p0, &
591  rho_in_situ, isq, ieq-isq+2, tv%eqn_of_state)
592  endif
593  do i=isq,ieq+1
594  dm(i,j) = (cs%GFS_scale - 1.0) * (g_rho0 * rho_in_situ(i)) * e(i,j,1)
595  enddo
596  enddo
597  else
598 !$OMP do
599  do j=jsq,jeq+1 ; do i=isq,ieq+1
600  dm(i,j) = (cs%GFS_scale - 1.0) * (g_rho0 * gv%Rlay(1)) * e(i,j,1)
601  enddo ; enddo
602  endif
603  endif
604 !$OMP end parallel
605 
606 ! Have checked that rho_0 drops out and that the 1-layer case is right. RWH.
607 
608  ! If regridding is activated, do a linear reconstruction of salinity
609  ! and temperature across each layer. The subscripts 't' and 'b' refer
610  ! to top and bottom values within each layer (these are the only degrees
611  ! of freedeom needed to know the linear profile).
612  if ( use_ale ) then
613  if ( prscheme == pressure_reconstruction_plm ) then
614  call pressure_gradient_plm (ale_csp, s_t, s_b, t_t, t_b, g, gv, tv, h);
615  elseif ( prscheme == pressure_reconstruction_ppm ) then
616  call pressure_gradient_ppm (ale_csp, s_t, s_b, t_t, t_b, g, gv, tv, h);
617  endif
618  endif
619 
620 !$OMP parallel do default(none) shared(use_p_atm,rho_ref,G,GV,e, &
621 !$OMP p_atm,nz,use_EOS,use_ALE,PRScheme,T_t,T_b,S_t, &
622 !$OMP S_b,CS,tv,tv_tmp,h,PFu,I_Rho0,h_neglect,PFv,dM)&
623 !$OMP private(is_bk,ie_bk,js_bk,je_bk,Isq_bk,Ieq_bk,Jsq_bk, &
624 !$OMP Jeq_bk,ioff_bk,joff_bk,pa_bk, &
625 !$OMP intx_pa_bk,inty_pa_bk,dpa_bk,intz_dpa_bk, &
626 !$OMP intx_dpa_bk,inty_dpa_bk,dz_bk,i,j)
627  do n = 1, g%nblocks
628  is_bk=g%Block(n)%isc ; ie_bk=g%Block(n)%iec
629  js_bk=g%Block(n)%jsc ; je_bk=g%Block(n)%jec
630  isq_bk=g%Block(n)%IscB ; ieq_bk=g%Block(n)%IecB
631  jsq_bk=g%Block(n)%JscB ; jeq_bk=g%Block(n)%JecB
632  ioff_bk = g%Block(n)%idg_offset - g%HI%idg_offset
633  joff_bk = g%Block(n)%jdg_offset - g%HI%jdg_offset
634 
635  ! Set the surface boundary conditions on pressure anomaly and its horizontal
636  ! integrals, assuming that the surface pressure anomaly varies linearly
637  ! in x and y.
638  if (use_p_atm) then
639  do jb=jsq_bk,jeq_bk+1 ; do ib=isq_bk,ieq_bk+1
640  i = ib+ioff_bk ; j = jb+joff_bk
641  pa_bk(ib,jb) = (rho_ref*gv%g_Earth)*e(i,j,1) + p_atm(i,j)
642  enddo ; enddo
643  else
644  do jb=jsq_bk,jeq_bk+1 ; do ib=isq_bk,ieq_bk+1
645  i = ib+ioff_bk ; j = jb+joff_bk
646  pa_bk(ib,jb) = (rho_ref*gv%g_Earth)*e(i,j,1)
647  enddo ; enddo
648  endif
649  do jb=js_bk,je_bk ; do ib=isq_bk,ieq_bk
650  intx_pa_bk(ib,jb) = 0.5*(pa_bk(ib,jb) + pa_bk(ib+1,jb))
651  enddo ; enddo
652  do jb=jsq_bk,jeq_bk ; do ib=is_bk,ie_bk
653  inty_pa_bk(ib,jb) = 0.5*(pa_bk(ib,jb) + pa_bk(ib,jb+1))
654  enddo ; enddo
655 
656  do k=1,nz
657  ! Calculate 4 integrals through the layer that are required in the
658  ! subsequent calculation.
659 
660  if (use_eos) then
661  ! The following routine computes the integrals that are needed to
662  ! calculate the pressure gradient force. Linear profiles for T and S are
663  ! assumed when regridding is activated. Otherwise, the previous version
664  ! is used, whereby densities within each layer are constant no matter
665  ! where the layers are located.
666  if ( use_ale ) then
667  if ( prscheme == pressure_reconstruction_plm ) then
668  call int_density_dz_generic_plm ( t_t(:,:,k), t_b(:,:,k), &
669  s_t(:,:,k), s_b(:,:,k), e(:,:,k), e(:,:,k+1), &
670  rho_ref, cs%Rho0, gv%g_Earth, &
671  gv%H_subroundoff, g%bathyT, g%HI, g%Block(n), &
672  tv%eqn_of_state, dpa_bk, intz_dpa_bk, intx_dpa_bk, inty_dpa_bk, &
673  usemasswghtinterp = cs%useMassWghtInterp)
674  elseif ( prscheme == pressure_reconstruction_ppm ) then
675  call int_density_dz_generic_ppm ( tv%T(:,:,k), t_t(:,:,k), t_b(:,:,k), &
676  tv%S(:,:,k), s_t(:,:,k), s_b(:,:,k), e(:,:,k), e(:,:,k+1), &
677  rho_ref, cs%Rho0, gv%g_Earth, &
678  g%HI, g%Block(n), tv%eqn_of_state, dpa_bk, intz_dpa_bk, &
679  intx_dpa_bk, inty_dpa_bk)
680  endif
681  else
682  call int_density_dz(tv_tmp%T(:,:,k), tv_tmp%S(:,:,k), &
683  e(:,:,k), e(:,:,k+1), &
684  rho_ref, cs%Rho0, gv%g_Earth, g%HI, g%Block(n), tv%eqn_of_state, &
685  dpa_bk, intz_dpa_bk, intx_dpa_bk, inty_dpa_bk )
686  endif
687  do jb=jsq_bk,jeq_bk+1 ; do ib=isq_bk,ieq_bk+1
688  intz_dpa_bk(ib,jb) = intz_dpa_bk(ib,jb)*gv%m_to_H
689  enddo ; enddo
690  else
691  do jb=jsq_bk,jeq_bk+1 ; do ib=isq_bk,ieq_bk+1
692  i = ib+ioff_bk ; j = jb+joff_bk
693  dz_bk(ib,jb) = gv%g_Earth*gv%H_to_m*h(i,j,k)
694  dpa_bk(ib,jb) = (gv%Rlay(k) - rho_ref)*dz_bk(ib,jb)
695  intz_dpa_bk(ib,jb) = 0.5*(gv%Rlay(k) - rho_ref)*dz_bk(ib,jb)*h(i,j,k)
696  enddo ; enddo
697  do jb=js_bk,je_bk ; do ib=isq_bk,ieq_bk
698  intx_dpa_bk(ib,jb) = 0.5*(gv%Rlay(k) - rho_ref) * (dz_bk(ib,jb)+dz_bk(ib+1,jb))
699  enddo ; enddo
700  do jb=jsq_bk,jeq_bk ; do ib=is_bk,ie_bk
701  inty_dpa_bk(ib,jb) = 0.5*(gv%Rlay(k) - rho_ref) * (dz_bk(ib,jb)+dz_bk(ib,jb+1))
702  enddo ; enddo
703  endif
704 
705  ! Compute pressure gradient in x direction
706  do jb=js_bk,je_bk ; do ib=isq_bk,ieq_bk
707  i = ib+ioff_bk ; j = jb+joff_bk
708  pfu(i,j,k) = (((pa_bk(ib,jb)*h(i,j,k) + intz_dpa_bk(ib,jb)) - &
709  (pa_bk(ib+1,jb)*h(i+1,j,k) + intz_dpa_bk(ib+1,jb))) + &
710  ((h(i+1,j,k) - h(i,j,k)) * intx_pa_bk(ib,jb) - &
711  (e(i+1,j,k+1) - e(i,j,k+1)) * intx_dpa_bk(ib,jb) * gv%m_to_H)) * &
712  ((2.0*i_rho0*g%IdxCu(i,j)) / &
713  ((h(i,j,k) + h(i+1,j,k)) + h_neglect))
714  intx_pa_bk(ib,jb) = intx_pa_bk(ib,jb) + intx_dpa_bk(ib,jb)
715  enddo ; enddo
716  ! Compute pressure gradient in y direction
717  do jb=jsq_bk,jeq_bk ; do ib=is_bk,ie_bk
718  i = ib+ioff_bk ; j = jb+joff_bk
719  pfv(i,j,k) = (((pa_bk(ib,jb)*h(i,j,k) + intz_dpa_bk(ib,jb)) - &
720  (pa_bk(ib,jb+1)*h(i,j+1,k) + intz_dpa_bk(ib,jb+1))) + &
721  ((h(i,j+1,k) - h(i,j,k)) * inty_pa_bk(ib,jb) - &
722  (e(i,j+1,k+1) - e(i,j,k+1)) * inty_dpa_bk(ib,jb) * gv%m_to_H)) * &
723  ((2.0*i_rho0*g%IdyCv(i,j)) / &
724  ((h(i,j,k) + h(i,j+1,k)) + h_neglect))
725  inty_pa_bk(ib,jb) = inty_pa_bk(ib,jb) + inty_dpa_bk(ib,jb)
726  enddo ; enddo
727  do jb=jsq_bk,jeq_bk+1 ; do ib=isq_bk,ieq_bk+1
728  pa_bk(ib,jb) = pa_bk(ib,jb) + dpa_bk(ib,jb)
729  enddo ; enddo
730  enddo
731 
732  if (cs%GFS_scale < 1.0) then
733  do k=1,nz
734  do j=js_bk+joff_bk,je_bk+joff_bk ; do i=isq_bk+ioff_bk,ieq_bk+ioff_bk
735  pfu(i,j,k) = pfu(i,j,k) - (dm(i+1,j) - dm(i,j)) * g%IdxCu(i,j)
736  enddo ; enddo
737  do j=jsq_bk+joff_bk,jeq_bk+joff_bk ; do i=is_bk+ioff_bk,ie_bk+ioff_bk
738  pfv(i,j,k) = pfv(i,j,k) - (dm(i,j+1) - dm(i,j)) * g%IdyCv(i,j)
739  enddo ; enddo
740  enddo
741  endif
742  enddo
743 
744  if (present(pbce)) then
745  call set_pbce_bouss(e, tv_tmp, g, gv, gv%g_Earth, cs%Rho0, cs%GFS_scale, pbce)
746  endif
747 
748  if (present(eta)) then
749  if (cs%tides) then
750  ! eta is the sea surface height relative to a time-invariant geoid, for
751  ! comparison with what is used for eta in btstep. See how e was calculated
752  ! about 200 lines above.
753 !$OM parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,eta,e,e_tidal)
754  do j=jsq,jeq+1 ; do i=isq,ieq+1
755  eta(i,j) = e(i,j,1)*gv%m_to_H + e_tidal(i,j)*gv%m_to_H
756  enddo ; enddo
757  else
758 !$OM parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,eta,e)
759  do j=jsq,jeq+1 ; do i=isq,ieq+1
760  eta(i,j) = e(i,j,1)*gv%m_to_H
761  enddo ; enddo
762  endif
763  endif
764 
765  if (cs%id_e_tidal>0) call post_data(cs%id_e_tidal, e_tidal, cs%diag)
766 
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pressureforce_afv_end()

subroutine, public mom_pressureforce_afv::pressureforce_afv_end ( type(pressureforce_afv_cs), pointer  CS)

Deallocates the finite volume pressure gradient control structure.

Definition at line 821 of file MOM_PressureForce_analytic_FV.F90.

821  type(pressureforce_afv_cs), pointer :: cs
822  if (associated(cs)) deallocate(cs)

◆ pressureforce_afv_init()

subroutine, public mom_pressureforce_afv::pressureforce_afv_init ( type(time_type), intent(in), target  Time,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
type(param_file_type), intent(in)  param_file,
type(diag_ctrl), intent(inout), target  diag,
type(pressureforce_afv_cs), pointer  CS,
type(tidal_forcing_cs), optional, pointer  tides_CSp 
)

Initializes the finite volume pressure gradient control structure.

Parameters
[in]timeCurrent model time
[in]gOcean grid structure
[in]gvVertical grid structure
[in]param_fileParameter file handles
[in,out]diagDiagnostics control structure
csFinite volume PGF control structure
tides_cspTides control structure

Definition at line 771 of file MOM_PressureForce_analytic_FV.F90.

References mom_error_handler::mom_error().

Referenced by mom_pressureforce::pressureforce_init().

771  type(time_type), target, intent(in) :: time !< Current model time
772  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
773  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure
774  type(param_file_type), intent(in) :: param_file !< Parameter file handles
775  type(diag_ctrl), target, intent(inout) :: diag !< Diagnostics control structure
776  type(pressureforce_afv_cs), pointer :: cs !< Finite volume PGF control structure
777  type(tidal_forcing_cs), optional, pointer :: tides_csp !< Tides control structure
778 ! This include declares and sets the variable "version".
779 #include "version_variable.h"
780  character(len=40) :: mdl ! This module's name.
781 
782  if (associated(cs)) then
783  call mom_error(warning, "PressureForce_init called with an associated "// &
784  "control structure.")
785  return
786  else ; allocate(cs) ; endif
787 
788  cs%diag => diag ; cs%Time => time
789  if (present(tides_csp)) then
790  if (associated(tides_csp)) cs%tides_CSp => tides_csp
791  endif
792 
793  mdl = "MOM_PressureForce_AFV"
794  call log_version(param_file, mdl, version, "")
795  call get_param(param_file, mdl, "RHO_0", cs%Rho0, &
796  "The mean ocean density used with BOUSSINESQ true to \n"//&
797  "calculate accelerations and the mass for conservation \n"//&
798  "properties, or with BOUSSINSEQ false to convert some \n"//&
799  "parameters from vertical units of m to kg m-2.", &
800  units="kg m-3", default=1035.0)
801  call get_param(param_file, mdl, "TIDES", cs%tides, &
802  "If true, apply tidal momentum forcing.", default=.false.)
803  call get_param(param_file, mdl, "MASS_WEIGHT_IN_PRESSURE_GRADIENT", cs%useMassWghtInterp, &
804  "If true, use mass weighting when interpolation T/S for\n"//&
805  "top/bottom integrals in AFV pressure gradient calculation.", default=.false.)
806 
807  if (cs%tides) then
808  cs%id_e_tidal = register_diag_field('ocean_model', 'e_tidal', diag%axesT1, &
809  time, 'Tidal Forcing Astronomical and SAL Height Anomaly', 'meter')
810  endif
811 
812  cs%GFS_scale = 1.0
813  if (gv%g_prime(1) /= gv%g_Earth) cs%GFS_scale = gv%g_prime(1) / gv%g_Earth
814 
815  call log_param(param_file, mdl, "GFS / G_EARTH", cs%GFS_scale)
816 
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pressureforce_afv_nonbouss()

subroutine, public mom_pressureforce_afv::pressureforce_afv_nonbouss ( real, dimension(szi_(g),szj_(g),szk_(g)), intent(in)  h,
type(thermo_var_ptrs), intent(in)  tv,
real, dimension(szib_(g),szj_(g),szk_(g)), intent(out)  PFu,
real, dimension(szi_(g),szjb_(g),szk_(g)), intent(out)  PFv,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
type(pressureforce_afv_cs), pointer  CS,
real, dimension(:,:), optional, pointer  p_atm,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(out), optional  pbce,
real, dimension(szi_(g),szj_(g)), intent(out), optional  eta 
)

Non-Boussinesq analytically-integrated finite volume form of pressure gradient.

Determines the acceleration due to hydrostatic pressure forces, using the analytic finite volume form of the Pressure gradient, and does not make the Boussinesq approximation.

To work, the following fields must be set outside of the usual ie to ie, je to je range before this subroutine is called: h[ie+1] and h[je+1] and (if tveqn_of_state is set) T[ie+1], S[ie+1], T[je+1], and S[je+1].

Parameters
[in]gOcean grid structure
[in]gvVertical grid structure
[in]hLayer thickness (kg/m2)
[in]tvThermodynamic variables
[out]pfuZonal acceleration (m/s2)
[out]pfvMeridional acceleration (m/s2)
csFinite volume PGF control structure
p_atmThe pressure at the ice-ocean or atmosphere-ocean interface in Pa.
[out]pbceThe baroclinic pressure anomaly in each layer due to eta anomalies, in m2 s-2 H-1.
[out]etaThe bottom mass used to calculate PFu and PFv, in H, with any tidal contributions or compressibility compensation.

Definition at line 87 of file MOM_PressureForce_analytic_FV.F90.

References mom_tidal_forcing::calc_tidal_forcing(), mom_error_handler::mom_error(), and mom_pressureforce_mont::set_pbce_nonbouss().

Referenced by pressureforce_afv().

87  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
88  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure
89  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness (kg/m2)
90  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables
91  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)), intent(out) :: pfu !< Zonal acceleration (m/s2)
92  real, dimension(SZI_(G),SZJB_(G),SZK_(G)), intent(out) :: pfv !< Meridional acceleration (m/s2)
93  type(pressureforce_afv_cs), pointer :: cs !< Finite volume PGF control structure
94  real, dimension(:,:), optional, pointer :: p_atm !< The pressure at the ice-ocean
95  !! or atmosphere-ocean interface in Pa.
96  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), optional, intent(out) :: pbce !< The baroclinic pressure
97  !! anomaly in each layer due to eta anomalies,
98  !! in m2 s-2 H-1.
99  real, dimension(SZI_(G),SZJ_(G)), optional, intent(out) :: eta !< The bottom mass used to
100  !! calculate PFu and PFv, in H, with any tidal
101  !! contributions or compressibility compensation.
102  ! Local variables
103  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1) :: p ! Interface pressure in Pa.
104  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), target :: &
105  t_tmp, & ! Temporary array of temperatures where layers that are lighter
106  ! than the mixed layer have the mixed layer's properties, in C.
107  s_tmp ! Temporary array of salinities where layers that are lighter
108  ! than the mixed layer have the mixed layer's properties, in psu.
109  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
110  dza, & ! The change in geopotential anomaly between the top and bottom
111  ! of a layer, in m2 s-2.
112  intp_dza ! The vertical integral in depth of the pressure anomaly less
113  ! the pressure anomaly at the top of the layer, in Pa m2 s-2.
114  real, dimension(SZI_(G),SZJ_(G)) :: &
115  dp, & ! The (positive) change in pressure across a layer, in Pa.
116  ssh, & ! The sea surface height anomaly, in m.
117  e_tidal, & ! The bottom geopotential anomaly due to tidal forces from
118  ! astronomical sources and self-attraction and loading, in m.
119  dm, & ! The barotropic adjustment to the Montgomery potential to
120  ! account for a reduced gravity model, in m2 s-2.
121  za ! The geopotential anomaly (i.e. g*e + alpha_0*pressure) at the
122  ! interface atop a layer, in m2 s-2.
123  real, dimension(SZDI_(G%Block(1)),SZDJ_(G%Block(1))) :: & ! on block indices
124  dp_bk, & ! The (positive) change in pressure across a layer, in Pa.
125  za_bk ! The geopotential anomaly (i.e. g*e + alpha_0*pressure) at the
126  ! interface atop a layer, in m2 s-2.
127 
128  real, dimension(SZI_(G)) :: rho_cv_bl ! The coordinate potential density in the deepest variable
129  ! density near-surface layer, in kg m-3.
130  real, dimension(SZDIB_(G%Block(1)),SZDJ_(G%Block(1))) :: & ! on block indices
131  intx_za_bk ! The zonal integral of the geopotential anomaly along the
132  ! interface below a layer, divided by the grid spacing, m2 s-2.
133  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)) :: &
134  intx_dza ! The change in intx_za through a layer, in m2 s-2.
135  real, dimension(SZDI_(G%Block(1)),SZDJB_(G%Block(1))) :: & ! on block indices
136  inty_za_bk ! The meridional integral of the geopotential anomaly along the
137  ! interface below a layer, divided by the grid spacing, m2 s-2.
138  real, dimension(SZI_(G),SZJB_(G),SZK_(G)) :: &
139  inty_dza ! The change in inty_za through a layer, in m2 s-2.
140  real :: p_ref(szi_(g)) ! The pressure used to calculate the coordinate
141  ! density, in Pa (usually 2e7 Pa = 2000 dbar).
142 
143  real :: dp_neglect ! A thickness that is so small it is usually lost
144  ! in roundoff and can be neglected, in Pa.
145  real :: alpha_anom ! The in-situ specific volume, averaged over a
146  ! layer, less alpha_ref, in m3 kg-1.
147  logical :: use_p_atm ! If true, use the atmospheric pressure.
148  logical :: use_eos ! If true, density is calculated from T & S using an
149  ! equation of state.
150  type(thermo_var_ptrs) :: tv_tmp! A structure of temporary T & S.
151 
152  real :: alpha_ref ! A reference specific volume, in m3 kg-1, that is used
153  ! to reduce the impact of truncation errors.
154  real :: rho_in_situ(szi_(g)) ! The in situ density, in kg m-3.
155  real :: pa_to_h ! A factor to convert from Pa to the thicknesss units (H).
156 ! real :: oneatm = 101325.0 ! 1 atm in Pa (kg/ms2)
157  real :: i_gearth
158  real, parameter :: c1_6 = 1.0/6.0
159  integer :: is, ie, js, je, isq, ieq, jsq, jeq, nz, nkmb
160  integer :: is_bk, ie_bk, js_bk, je_bk, isq_bk, ieq_bk, jsq_bk, jeq_bk
161  integer :: i, j, k, n, ib, jb, ioff_bk, joff_bk
162 
163  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
164  nkmb=gv%nk_rho_varies
165  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
166 
167  use_p_atm = .false.
168  if (present(p_atm)) then ; if (associated(p_atm)) use_p_atm = .true. ; endif
169  use_eos = associated(tv%eqn_of_state)
170 
171  if (.not.associated(cs)) call mom_error(fatal, &
172  "MOM_PressureForce: Module must be initialized before it is used.")
173 
174  dp_neglect = gv%H_to_Pa * gv%H_subroundoff
175  alpha_ref = 1.0/cs%Rho0
176 
177 !$OMP parallel default(none) shared(Isq,Ieq,Jsq,Jeq,nz,use_p_atm,p,p_atm,GV,h)
178  if (use_p_atm) then
179 !$OMP do
180  do j=jsq,jeq+1 ; do i=isq,ieq+1
181  p(i,j,1) = p_atm(i,j)
182  enddo ; enddo
183  else
184 !$OMP do
185  do j=jsq,jeq+1 ; do i=isq,ieq+1
186  p(i,j,1) = 0.0 ! or oneatm
187  enddo ; enddo
188  endif
189 !$OMP do
190  do j=jsq,jeq+1 ; do k=2,nz+1 ; do i=isq,ieq+1
191  p(i,j,k) = p(i,j,k-1) + gv%H_to_Pa * h(i,j,k-1)
192  enddo ; enddo ; enddo
193 !$OMP end parallel
194 
195  i_gearth = 1.0 / gv%g_Earth
196 
197  if (use_eos) then
198  ! With a bulk mixed layer, replace the T & S of any layers that are
199  ! lighter than the the buffer layer with the properties of the buffer
200  ! layer. These layers will be massless anyway, and it avoids any
201  ! formal calculations with hydrostatically unstable profiles.
202  if (nkmb>0) then
203  tv_tmp%T => t_tmp ; tv_tmp%S => s_tmp
204  tv_tmp%eqn_of_state => tv%eqn_of_state
205  do i=isq,ieq+1 ; p_ref(i) = tv%P_Ref ; enddo
206 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,nz,nkmb,tv_tmp,tv,p_ref,GV) &
207 !$OMP private(Rho_cv_BL)
208  do j=jsq,jeq+1
209  do k=1,nkmb ; do i=isq,ieq+1
210  tv_tmp%T(i,j,k) = tv%T(i,j,k) ; tv_tmp%S(i,j,k) = tv%S(i,j,k)
211  enddo ; enddo
212  call calculate_density(tv%T(:,j,nkmb), tv%S(:,j,nkmb), p_ref, &
213  rho_cv_bl(:), isq, ieq-isq+2, tv%eqn_of_state)
214  do k=nkmb+1,nz ; do i=isq,ieq+1
215  if (gv%Rlay(k) < rho_cv_bl(i)) then
216  tv_tmp%T(i,j,k) = tv%T(i,j,nkmb) ; tv_tmp%S(i,j,k) = tv%S(i,j,nkmb)
217  else
218  tv_tmp%T(i,j,k) = tv%T(i,j,k) ; tv_tmp%S(i,j,k) = tv%S(i,j,k)
219  endif
220  enddo ; enddo
221  enddo
222  else
223  tv_tmp%T => tv%T ; tv_tmp%S => tv%S
224  tv_tmp%eqn_of_state => tv%eqn_of_state
225  endif
226  endif
227 
228 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,nz,is,ie,js,je,tv_tmp,alpha_ref, &
229 !$OMP p,h,G,GV,tv,dza,intp_dza,intx_dza,inty_dza,use_EOS) &
230 !$OMP private(alpha_anom,dp)
231  do k=1,nz
232  ! Calculate 4 integrals through the layer that are required in the
233  ! subsequent calculation.
234  if (use_eos) then
235  call int_specific_vol_dp(tv_tmp%T(:,:,k), tv_tmp%S(:,:,k), p(:,:,k), &
236  p(:,:,k+1), alpha_ref, g%HI, tv%eqn_of_state, &
237  dza(:,:,k), intp_dza(:,:,k), intx_dza(:,:,k), &
238  inty_dza(:,:,k))
239  else
240  alpha_anom = 1.0/gv%Rlay(k) - alpha_ref
241  do j=jsq,jeq+1 ; do i=isq,ieq+1
242  dp(i,j) = gv%H_to_Pa * h(i,j,k)
243  dza(i,j,k) = alpha_anom * dp(i,j)
244  intp_dza(i,j,k) = 0.5 * alpha_anom * dp(i,j)**2
245  enddo ; enddo
246  do j=js,je ; do i=isq,ieq
247  intx_dza(i,j,k) = 0.5 * alpha_anom * (dp(i,j)+dp(i+1,j))
248  enddo ; enddo
249  do j=jsq,jeq ; do i=is,ie
250  inty_dza(i,j,k) = 0.5 * alpha_anom * (dp(i,j)+dp(i,j+1))
251  enddo ; enddo
252  endif
253  enddo
254 
255  ! The bottom geopotential anomaly is calculated first so that the increments
256  ! to the geopotential anomalies can be reused. Alternately, the surface
257  ! geopotential could be calculated directly with separate calls to
258  ! int_specific_vol_dp with alpha_ref=0, and the anomalies used going
259  ! downward, which would relieve the need for dza, intp_dza, intx_dza, and
260  ! inty_dza to be 3-D arrays.
261 
262  ! Sum vertically to determine the surface geopotential anomaly.
263 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,nz,za,alpha_ref,p,G,GV,dza)
264  do j=jsq,jeq+1
265  do i=isq,ieq+1
266  za(i,j) = alpha_ref*p(i,j,nz+1) - gv%g_Earth*g%bathyT(i,j)
267  enddo
268  do k=nz,1,-1 ; do i=isq,ieq+1
269  za(i,j) = za(i,j) + dza(i,j,k)
270  enddo ; enddo
271  enddo
272 
273  if (cs%tides) then
274  ! Find and add the tidal geopotential anomaly.
275 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,SSH,za,alpha_ref,p,I_gEarth)
276  do j=jsq,jeq+1 ; do i=isq,ieq+1
277  ssh(i,j) = (za(i,j) - alpha_ref*p(i,j,1)) * i_gearth
278  enddo ; enddo
279  call calc_tidal_forcing(cs%Time, ssh, e_tidal, g, cs%tides_CSp)
280 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,za,G,GV,e_tidal)
281  do j=jsq,jeq+1 ; do i=isq,ieq+1
282  za(i,j) = za(i,j) - gv%g_Earth*e_tidal(i,j)
283  enddo ; enddo
284  endif
285 
286  if (cs%GFS_scale < 1.0) then
287  ! Adjust the Montgomery potential to make this a reduced gravity model.
288  if (use_eos) then
289 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,tv_tmp,p,tv,dM,CS,alpha_ref,za) &
290 !$OMP private(rho_in_situ)
291  do j=jsq,jeq+1
292  call calculate_density(tv_tmp%T(:,j,1), tv_tmp%S(:,j,1), p(:,j,1), &
293  rho_in_situ, isq, ieq-isq+2, tv%eqn_of_state)
294 
295  do i=isq,ieq+1
296  dm(i,j) = (cs%GFS_scale - 1.0) * &
297  (p(i,j,1)*(1.0/rho_in_situ(i) - alpha_ref) + za(i,j))
298  enddo
299  enddo
300  else
301 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,dM,CS,p,GV,alpha_ref,za)
302  do j=jsq,jeq+1 ; do i=isq,ieq+1
303  dm(i,j) = (cs%GFS_scale - 1.0) * &
304  (p(i,j,1)*(1.0/gv%Rlay(1) - alpha_ref) + za(i,j))
305  enddo ; enddo
306  endif
307 ! else
308 ! do j=Jsq,Jeq+1 ; do i=Isq,Ieq+1 ; dM(i,j) = 0.0 ; enddo ; enddo
309  endif
310 
311  ! This order of integrating upward and then downward again is necessary with
312  ! a nonlinear equation of state, so that the surface geopotentials will go
313  ! linearly between the values at thickness points, but the bottom
314  ! geopotentials will not now be linear at the sub-grid-scale. Doing this
315  ! ensures no motion with flat isopycnals, even with a nonlinear equation of state.
316 !$OMP parallel do default(none) shared(nz,za,G,GV,dza,intx_dza,h,PFu, &
317 !$OMP intp_dza,p,dp_neglect,inty_dza,PFv,CS,dM) &
318 !$OMP private(is_bk,ie_bk,js_bk,je_bk,Isq_bk,Ieq_bk,Jsq_bk, &
319 !$OMP Jeq_bk,ioff_bk,joff_bk,i,j,za_bk,intx_za_bk, &
320 !$OMP inty_za_bk,dp_bk)
321  do n = 1, g%nblocks
322  is_bk=g%block(n)%isc ; ie_bk=g%block(n)%iec
323  js_bk=g%block(n)%jsc ; je_bk=g%block(n)%jec
324  isq_bk=g%block(n)%IscB ; ieq_bk=g%block(n)%IecB
325  jsq_bk=g%block(n)%JscB ; jeq_bk=g%block(n)%JecB
326  ioff_bk = g%Block(n)%idg_offset - g%HI%idg_offset
327  joff_bk = g%Block(n)%jdg_offset - g%HI%jdg_offset
328  do jb=jsq_bk,jeq_bk+1 ; do ib=isq_bk,ieq_bk+1
329  i = ib+ioff_bk ; j = jb+joff_bk
330  za_bk(ib,jb) = za(i,j)
331  enddo ; enddo
332  do jb=js_bk,je_bk ; do ib=isq_bk,ieq_bk
333  i = ib+ioff_bk ; j = jb+joff_bk
334  intx_za_bk(ib,jb) = 0.5*(za_bk(ib,jb) + za_bk(ib+1,jb))
335  enddo ; enddo
336  do jb=jsq_bk,jeq_bk ; do ib=is_bk,ie_bk
337  i = ib+ioff_bk ; j = jb+joff_bk
338  inty_za_bk(ib,jb) = 0.5*(za_bk(ib,jb) + za_bk(ib,jb+1))
339  enddo ; enddo
340  do k=1,nz
341  ! These expressions for the acceleration have been carefully checked in
342  ! a set of idealized cases, and should be bug-free.
343  do jb=jsq_bk,jeq_bk+1 ; do ib=isq_bk,ieq_bk+1
344  i = ib+ioff_bk ; j = jb+joff_bk
345  dp_bk(ib,jb) = gv%H_to_Pa*h(i,j,k)
346  za_bk(ib,jb) = za_bk(ib,jb) - dza(i,j,k)
347  enddo ; enddo
348  do jb=js_bk,je_bk ; do ib=isq_bk,ieq_bk
349  i = ib+ioff_bk ; j = jb+joff_bk
350  intx_za_bk(ib,jb) = intx_za_bk(ib,jb) - intx_dza(i,j,k)
351  pfu(i,j,k) = (((za_bk(ib,jb)*dp_bk(ib,jb) + intp_dza(i,j,k)) - &
352  (za_bk(ib+1,jb)*dp_bk(ib+1,jb) + intp_dza(i+1,j,k))) + &
353  ((dp_bk(ib+1,jb) - dp_bk(ib,jb)) * intx_za_bk(ib,jb) - &
354  (p(i+1,j,k) - p(i,j,k)) * intx_dza(i,j,k))) * &
355  (2.0*g%IdxCu(i,j) / ((dp_bk(ib,jb) + dp_bk(ib+1,jb)) + &
356  dp_neglect))
357  enddo ; enddo
358  do jb=jsq_bk,jeq_bk ; do ib=is_bk,ie_bk
359  i = ib+ioff_bk ; j = jb+joff_bk
360  inty_za_bk(ib,jb) = inty_za_bk(ib,jb) - inty_dza(i,j,k)
361  pfv(i,j,k) = (((za_bk(ib,jb)*dp_bk(ib,jb) + intp_dza(i,j,k)) - &
362  (za_bk(ib,jb+1)*dp_bk(ib,jb+1) + intp_dza(i,j+1,k))) + &
363  ((dp_bk(ib,jb+1) - dp_bk(ib,jb)) * inty_za_bk(ib,jb) - &
364  (p(i,j+1,k) - p(i,j,k)) * inty_dza(i,j,k))) * &
365  (2.0*g%IdyCv(i,j) / ((dp_bk(ib,jb) + dp_bk(ib,jb+1)) + &
366  dp_neglect))
367  enddo ; enddo
368 
369  if (cs%GFS_scale < 1.0) then
370  ! Adjust the Montgomery potential to make this a reduced gravity model.
371  do j=js_bk+joff_bk,je_bk+joff_bk ; do i=isq_bk+ioff_bk,ieq_bk+ioff_bk
372  pfu(i,j,k) = pfu(i,j,k) - (dm(i+1,j) - dm(i,j)) * g%IdxCu(i,j)
373  enddo ; enddo
374  do j=jsq_bk+joff_bk,jeq_bk+joff_bk ; do i=is_bk+ioff_bk,ie_bk+ioff_bk
375  pfv(i,j,k) = pfv(i,j,k) - (dm(i,j+1) - dm(i,j)) * g%IdyCv(i,j)
376  enddo ; enddo
377  endif
378  enddo
379  enddo
380 
381  if (present(pbce)) then
382  call set_pbce_nonbouss(p, tv_tmp, g, gv, gv%g_Earth, cs%GFS_scale, pbce)
383  endif
384 
385  if (present(eta)) then
386  pa_to_h = 1.0 / gv%H_to_Pa
387  if (use_p_atm) then
388 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,nz,eta,p,p_atm,Pa_to_H)
389  do j=jsq,jeq+1 ; do i=isq,ieq+1
390  eta(i,j) = (p(i,j,nz+1) - p_atm(i,j))*pa_to_h ! eta has the same units as h.
391  enddo ; enddo
392  else
393 !$OMP parallel do default(none) shared(Isq,Ieq,Jsq,Jeq,nz,eta,p,Pa_to_H)
394  do j=jsq,jeq+1 ; do i=isq,ieq+1
395  eta(i,j) = p(i,j,nz+1)*pa_to_h ! eta has the same units as h.
396  enddo ; enddo
397  endif
398  endif
399 
400  if (cs%id_e_tidal>0) call post_data(cs%id_e_tidal, e_tidal, cs%diag)
401 
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
Here is the call graph for this function:
Here is the caller graph for this function: