MOM6
MOM_isopycnal_slopes.F90
1 !> Calculations of isoneutral slopes and stratification.
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_grid, only : ocean_grid_type
10 use mom_eos, only : int_specific_vol_dp, calculate_density_derivs
11 
12 implicit none ; private
13 
14 #include <MOM_memory.h>
15 
16 public calc_isoneutral_slopes, vert_fill_ts
17 
18 ! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
19 ! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
20 ! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
21 ! vary with the Boussinesq approximation, the Boussinesq variant is given first.
22 
23 contains
24 
25 !> Calculate isopycnal slopes, and optionally return N2 used in calculation.
26 subroutine calc_isoneutral_slopes(G, GV, US, h, e, tv, dt_kappa_smooth, &
27  slope_x, slope_y, N2_u, N2_v, halo) !, eta_to_m)
28  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
29  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
30  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
31  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
32  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1), intent(in) :: e !< Interface heights [Z ~> m] or units
33  !! given by 1/eta_to_m)
34  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various
35  !! thermodynamic variables
36  real, intent(in) :: dt_kappa_smooth !< A smoothing vertical diffusivity
37  !! times a smoothing timescale [Z2 ~> m2].
38  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)+1), intent(inout) :: slope_x !< Isopycnal slope in i-direction [nondim]
39  real, dimension(SZI_(G),SZJB_(G),SZK_(G)+1), intent(inout) :: slope_y !< Isopycnal slope in j-direction [nondim]
40  real, dimension(SZIB_(G),SZJ_(G),SZK_(G)+1), &
41  optional, intent(inout) :: n2_u !< Brunt-Vaisala frequency squared at
42  !! interfaces between u-points [s-2]
43  real, dimension(SZI_(G),SZJB_(G),SZK_(G)+1), &
44  optional, intent(inout) :: n2_v !< Brunt-Vaisala frequency squared at
45  !! interfaces between u-points [s-2]
46  integer, optional, intent(in) :: halo !< Halo width over which to compute
47 
48  ! real, optional, intent(in) :: eta_to_m !< The conversion factor from the units
49  ! (This argument has been tested but for now serves no purpose.) !! of eta to m; US%Z_to_m by default.
50  ! Local variables
51  real, dimension(SZI_(G), SZJ_(G), SZK_(G)) :: &
52  t, & ! The temperature [degC], with the values in
53  ! in massless layers filled vertically by diffusion.
54  s, & ! The filled salinity [ppt], with the values in
55  ! in massless layers filled vertically by diffusion.
56  rho ! Density itself, when a nonlinear equation of state is not in use [kg m-3].
57  real, dimension(SZI_(G), SZJ_(G), SZK_(G)+1) :: &
58  pres ! The pressure at an interface [Pa].
59  real, dimension(SZIB_(G)) :: &
60  drho_dt_u, & ! The derivative of density with temperature at u points [kg m-3 degC-1].
61  drho_ds_u ! The derivative of density with salinity at u points [kg m-3 ppt-1].
62  real, dimension(SZI_(G)) :: &
63  drho_dt_v, & ! The derivative of density with temperature at v points [kg m-3 degC-1].
64  drho_ds_v ! The derivative of density with salinity at v points [kg m-3 ppt-1].
65  real, dimension(SZIB_(G)) :: &
66  t_u, & ! Temperature on the interface at the u-point [degC].
67  s_u, & ! Salinity on the interface at the u-point [ppt].
68  pres_u ! Pressure on the interface at the u-point [Pa].
69  real, dimension(SZI_(G)) :: &
70  t_v, & ! Temperature on the interface at the v-point [degC].
71  s_v, & ! Salinity on the interface at the v-point [ppt].
72  pres_v ! Pressure on the interface at the v-point [Pa].
73  real :: drdia, drdib ! Along layer zonal- and meridional- potential density
74  real :: drdja, drdjb ! gradients in the layers above (A) and below(B) the
75  ! interface times the grid spacing [kg m-3].
76  real :: drdkl, drdkr ! Vertical density differences across an interface [kg m-3].
77  real :: hg2a, hg2b ! Squares of geometric mean thicknesses [H2 ~> m2 or kg2 m-4].
78  real :: hg2l, hg2r ! Squares of geometric mean thicknesses [H2 ~> m2 or kg2 m-4].
79  real :: haa, hab, hal, har ! Arithmetic mean thicknesses [H ~> m or kg m-2].
80  real :: dzal, dzar ! Temporary thicknesses in eta units [Z ~> m].
81  real :: wta, wtb, wtl, wtr ! Unscaled weights, with various units.
82  real :: drdx, drdy ! Zonal and meridional density gradients [kg m-4].
83  real :: drdz ! Vertical density gradient [kg m-3 Z-1 ~> kg m-4].
84  real :: slope ! The slope of density surfaces, calculated in a way
85  ! that is always between -1 and 1.
86  real :: mag_grad2 ! The squared magnitude of the 3-d density gradient [kg2 m-8].
87  real :: slope2_ratio ! The ratio of the slope squared to slope_max squared.
88  real :: h_neglect ! A thickness that is so small it is usually lost
89  ! in roundoff and can be neglected [H ~> m or kg m-2].
90  real :: h_neglect2 ! h_neglect^2 [H2 ~> m2 or kg2 m-4].
91  real :: dz_neglect ! A change in interface heighs that is so small it is usually lost
92  ! in roundoff and can be neglected [Z ~> m].
93  logical :: use_eos ! If true, density is calculated from T & S using an
94  ! equation of state.
95  real :: g_rho0, n2, dzn2, h_x(szib_(g)), h_y(szi_(g))
96  real :: z_to_l ! A conversion factor between from units for e to the
97  ! units for lateral distances.
98  real :: l_to_z ! A conversion factor between from units for lateral distances
99  ! to the units for e.
100  real :: h_to_z ! A conversion factor from thickness units to the units of e.
101 
102  logical :: present_n2_u, present_n2_v
103  integer :: is, ie, js, je, nz, isdb
104  integer :: i, j, k
105 
106  if (present(halo)) then
107  is = g%isc-halo ; ie = g%iec+halo ; js = g%jsc-halo ; je = g%jec+halo
108  else
109  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
110  endif
111  nz = g%ke ; isdb = g%IsdB
112 
113  h_neglect = gv%H_subroundoff ; h_neglect2 = h_neglect**2
114  z_to_l = us%Z_to_m ; h_to_z = gv%H_to_Z
115  ! if (present(eta_to_m)) then
116  ! Z_to_L = eta_to_m ; H_to_Z = GV%H_to_m / eta_to_m
117  ! endif
118  l_to_z = 1.0 / z_to_l
119  dz_neglect = gv%H_subroundoff * h_to_z
120 
121  use_eos = associated(tv%eqn_of_state)
122 
123  present_n2_u = PRESENT(n2_u)
124  present_n2_v = PRESENT(n2_v)
125  g_rho0 = (us%L_to_Z*us%L_to_m*l_to_z*us%s_to_T**2*gv%g_Earth) / gv%Rho0
126  if (present_n2_u) then
127  do j=js,je ; do i=is-1,ie
128  n2_u(i,j,1) = 0.
129  n2_u(i,j,nz+1) = 0.
130  enddo ; enddo
131  endif
132  if (present_n2_v) then
133  do j=js-1,je ; do i=is,ie
134  n2_v(i,j,1) = 0.
135  n2_v(i,j,nz+1) = 0.
136  enddo ; enddo
137  endif
138 
139  if (use_eos) then
140  if (present(halo)) then
141  call vert_fill_ts(h, tv%T, tv%S, dt_kappa_smooth, t, s, g, gv, halo+1)
142  else
143  call vert_fill_ts(h, tv%T, tv%S, dt_kappa_smooth, t, s, g, gv, 1)
144  endif
145  endif
146 
147  ! Find the maximum and minimum permitted streamfunction.
148  !$OMP parallel do default(shared)
149  do j=js-1,je+1 ; do i=is-1,ie+1
150  pres(i,j,1) = 0.0 ! ### This should be atmospheric pressure.
151  pres(i,j,2) = pres(i,j,1) + gv%H_to_Pa*h(i,j,1)
152  enddo ; enddo
153  !$OMP parallel do default(shared)
154  do j=js-1,je+1
155  do k=2,nz ; do i=is-1,ie+1
156  pres(i,j,k+1) = pres(i,j,k) + gv%H_to_Pa*h(i,j,k)
157  enddo ; enddo
158  enddo
159 
160  !$OMP parallel do default(none) shared(nz,is,ie,js,je,IsdB,use_EOS,G,GV,pres,T,S,tv, &
161  !$OMP h,h_neglect,e,dz_neglect,Z_to_L,L_to_Z,H_to_Z, &
162  !$OMP h_neglect2,present_N2_u,G_Rho0,N2_u,slope_x) &
163  !$OMP private(drdiA,drdiB,drdkL,drdkR,pres_u,T_u,S_u, &
164  !$OMP drho_dT_u,drho_dS_u,hg2A,hg2B,hg2L,hg2R,haA, &
165  !$OMP haB,haL,haR,dzaL,dzaR,wtA,wtB,wtL,wtR,drdz, &
166  !$OMP drdx,mag_grad2,Slope,slope2_Ratio)
167  do j=js,je ; do k=nz,2,-1
168  if (.not.(use_eos)) then
169  drdia = 0.0 ; drdib = 0.0
170  drdkl = gv%Rlay(k)-gv%Rlay(k-1) ; drdkr = gv%Rlay(k)-gv%Rlay(k-1)
171  endif
172 
173  ! Calculate the zonal isopycnal slope.
174  if (use_eos) then
175  do i=is-1,ie
176  pres_u(i) = 0.5*(pres(i,j,k) + pres(i+1,j,k))
177  t_u(i) = 0.25*((t(i,j,k) + t(i+1,j,k)) + (t(i,j,k-1) + t(i+1,j,k-1)))
178  s_u(i) = 0.25*((s(i,j,k) + s(i+1,j,k)) + (s(i,j,k-1) + s(i+1,j,k-1)))
179  enddo
180  call calculate_density_derivs(t_u, s_u, pres_u, drho_dt_u, &
181  drho_ds_u, (is-isdb+1)-1, ie-is+2, tv%eqn_of_state)
182  endif
183 
184  do i=is-1,ie
185  if (use_eos) then
186  ! Estimate the horizontal density gradients along layers.
187  drdia = drho_dt_u(i) * (t(i+1,j,k-1)-t(i,j,k-1)) + &
188  drho_ds_u(i) * (s(i+1,j,k-1)-s(i,j,k-1))
189  drdib = drho_dt_u(i) * (t(i+1,j,k)-t(i,j,k)) + &
190  drho_ds_u(i) * (s(i+1,j,k)-s(i,j,k))
191 
192  ! Estimate the vertical density gradients times the grid spacing.
193  drdkl = (drho_dt_u(i) * (t(i,j,k)-t(i,j,k-1)) + &
194  drho_ds_u(i) * (s(i,j,k)-s(i,j,k-1)))
195  drdkr = (drho_dt_u(i) * (t(i+1,j,k)-t(i+1,j,k-1)) + &
196  drho_ds_u(i) * (s(i+1,j,k)-s(i+1,j,k-1)))
197  endif
198 
199 
200  if (use_eos) then
201  hg2a = h(i,j,k-1)*h(i+1,j,k-1) + h_neglect2
202  hg2b = h(i,j,k)*h(i+1,j,k) + h_neglect2
203  hg2l = h(i,j,k-1)*h(i,j,k) + h_neglect2
204  hg2r = h(i+1,j,k-1)*h(i+1,j,k) + h_neglect2
205  haa = 0.5*(h(i,j,k-1) + h(i+1,j,k-1))
206  hab = 0.5*(h(i,j,k) + h(i+1,j,k)) + h_neglect
207  hal = 0.5*(h(i,j,k-1) + h(i,j,k)) + h_neglect
208  har = 0.5*(h(i+1,j,k-1) + h(i+1,j,k)) + h_neglect
209  if (gv%Boussinesq) then
210  dzal = hal * h_to_z ; dzar = har * h_to_z
211  else
212  dzal = 0.5*(e(i,j,k-1) - e(i,j,k+1)) + dz_neglect
213  dzar = 0.5*(e(i+1,j,k-1) - e(i+1,j,k+1)) + dz_neglect
214  endif
215  ! Use the harmonic mean thicknesses to weight the horizontal gradients.
216  ! These unnormalized weights have been rearranged to minimize divisions.
217  wta = hg2a*hab ; wtb = hg2b*haa
218  wtl = hg2l*(har*dzar) ; wtr = hg2r*(hal*dzal)
219 
220  drdz = (wtl * drdkl + wtr * drdkr) / (dzal*wtl + dzar*wtr)
221  ! The expression for drdz above is mathematically equivalent to:
222  ! drdz = ((hg2L/haL) * drdkL/dzaL + (hg2R/haR) * drdkR/dzaR) / &
223  ! ((hg2L/haL) + (hg2R/haR))
224  ! This is the gradient of density along geopotentials.
225  drdx = ((wta * drdia + wtb * drdib) / (wta + wtb) - &
226  drdz * (e(i,j,k)-e(i+1,j,k))) * g%IdxCu(i,j)
227 
228  ! This estimate of slope is accurate for small slopes, but bounded
229  ! to be between -1 and 1.
230  mag_grad2 = drdx**2 + (l_to_z*drdz)**2
231  if (mag_grad2 > 0.0) then
232  slope_x(i,j,k) = drdx / sqrt(mag_grad2)
233  else ! Just in case mag_grad2 = 0 ever.
234  slope_x(i,j,k) = 0.0
235  endif
236 
237  if (present_n2_u) n2_u(i,j,k) = g_rho0 * drdz * g%mask2dCu(i,j) ! Square of Brunt-Vaisala frequency [s-2]
238 
239  else ! With .not.use_EOS, the layers are constant density.
240  slope_x(i,j,k) = (z_to_l*(e(i,j,k)-e(i+1,j,k))) * g%IdxCu(i,j)
241  endif
242 
243  enddo ! I
244  enddo ; enddo ! end of j-loop
245 
246  ! Calculate the meridional isopycnal slope.
247  !$OMP parallel do default(none) shared(nz,is,ie,js,je,IsdB,use_EOS,G,GV,pres,T,S,tv, &
248  !$OMP h,h_neglect,e,dz_neglect,Z_to_L,L_to_Z,H_to_Z, &
249  !$OMP h_neglect2,present_N2_v,G_Rho0,N2_v,slope_y) &
250  !$OMP private(drdjA,drdjB,drdkL,drdkR,pres_v,T_v,S_v, &
251  !$OMP drho_dT_v,drho_dS_v,hg2A,hg2B,hg2L,hg2R,haA, &
252  !$OMP haB,haL,haR,dzaL,dzaR,wtA,wtB,wtL,wtR,drdz, &
253  !$OMP drdy,mag_grad2,Slope,slope2_Ratio)
254  do j=js-1,je ; do k=nz,2,-1
255  if (.not.(use_eos)) then
256  drdja = 0.0 ; drdjb = 0.0
257  drdkl = gv%Rlay(k)-gv%Rlay(k-1) ; drdkr = gv%Rlay(k)-gv%Rlay(k-1)
258  endif
259 
260  if (use_eos) then
261  do i=is,ie
262  pres_v(i) = 0.5*(pres(i,j,k) + pres(i,j+1,k))
263  t_v(i) = 0.25*((t(i,j,k) + t(i,j+1,k)) + (t(i,j,k-1) + t(i,j+1,k-1)))
264  s_v(i) = 0.25*((s(i,j,k) + s(i,j+1,k)) + (s(i,j,k-1) + s(i,j+1,k-1)))
265  enddo
266  call calculate_density_derivs(t_v, s_v, pres_v, drho_dt_v, &
267  drho_ds_v, is, ie-is+1, tv%eqn_of_state)
268  endif
269  do i=is,ie
270  if (use_eos) then
271  ! Estimate the horizontal density gradients along layers.
272  drdja = drho_dt_v(i) * (t(i,j+1,k-1)-t(i,j,k-1)) + &
273  drho_ds_v(i) * (s(i,j+1,k-1)-s(i,j,k-1))
274  drdjb = drho_dt_v(i) * (t(i,j+1,k)-t(i,j,k)) + &
275  drho_ds_v(i) * (s(i,j+1,k)-s(i,j,k))
276 
277  ! Estimate the vertical density gradients times the grid spacing.
278  drdkl = (drho_dt_v(i) * (t(i,j,k)-t(i,j,k-1)) + &
279  drho_ds_v(i) * (s(i,j,k)-s(i,j,k-1)))
280  drdkr = (drho_dt_v(i) * (t(i,j+1,k)-t(i,j+1,k-1)) + &
281  drho_ds_v(i) * (s(i,j+1,k)-s(i,j+1,k-1)))
282  endif
283 
284  if (use_eos) then
285  hg2a = h(i,j,k-1)*h(i,j+1,k-1) + h_neglect2
286  hg2b = h(i,j,k)*h(i,j+1,k) + h_neglect2
287  hg2l = h(i,j,k-1)*h(i,j,k) + h_neglect2
288  hg2r = h(i,j+1,k-1)*h(i,j+1,k) + h_neglect2
289  haa = 0.5*(h(i,j,k-1) + h(i,j+1,k-1)) + h_neglect
290  hab = 0.5*(h(i,j,k) + h(i,j+1,k)) + h_neglect
291  hal = 0.5*(h(i,j,k-1) + h(i,j,k)) + h_neglect
292  har = 0.5*(h(i,j+1,k-1) + h(i,j+1,k)) + h_neglect
293  if (gv%Boussinesq) then
294  dzal = hal * h_to_z ; dzar = har * h_to_z
295  else
296  dzal = 0.5*(e(i,j,k-1) - e(i,j,k+1)) + dz_neglect
297  dzar = 0.5*(e(i,j+1,k-1) - e(i,j+1,k+1)) + dz_neglect
298  endif
299  ! Use the harmonic mean thicknesses to weight the horizontal gradients.
300  ! These unnormalized weights have been rearranged to minimize divisions.
301  wta = hg2a*hab ; wtb = hg2b*haa
302  wtl = hg2l*(har*dzar) ; wtr = hg2r*(hal*dzal)
303 
304  drdz = (wtl * drdkl + wtr * drdkr) / (dzal*wtl + dzar*wtr)
305  ! The expression for drdz above is mathematically equivalent to:
306  ! drdz = ((hg2L/haL) * drdkL/dzaL + (hg2R/haR) * drdkR/dzaR) / &
307  ! ((hg2L/haL) + (hg2R/haR))
308  ! This is the gradient of density along geopotentials.
309  drdy = ((wta * drdja + wtb * drdjb) / (wta + wtb) - &
310  drdz * (e(i,j,k)-e(i,j+1,k))) * g%IdyCv(i,j)
311 
312  ! This estimate of slope is accurate for small slopes, but bounded
313  ! to be between -1 and 1.
314  mag_grad2 = drdy**2 + (l_to_z*drdz)**2
315  if (mag_grad2 > 0.0) then
316  slope_y(i,j,k) = drdy / sqrt(mag_grad2)
317  else ! Just in case mag_grad2 = 0 ever.
318  slope_y(i,j,k) = 0.0
319  endif
320 
321  if (present_n2_v) n2_v(i,j,k) = g_rho0 * drdz * g%mask2dCv(i,j) ! Square of Brunt-Vaisala frequency [s-2]
322 
323  else ! With .not.use_EOS, the layers are constant density.
324  slope_y(i,j,k) = (z_to_l*(e(i,j,k)-e(i,j+1,k))) * g%IdyCv(i,j)
325  endif
326 
327  enddo ! i
328  enddo ; enddo ! end of j-loop
329 
330 end subroutine calc_isoneutral_slopes
331 
332 !> Returns tracer arrays (nominally T and S) with massless layers filled with
333 !! sensible values, by diffusing vertically with a small but constant diffusivity.
334 subroutine vert_fill_ts(h, T_in, S_in, kappa_dt, T_f, S_f, G, GV, halo_here, larger_h_denom)
335  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
336  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
337  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
338  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: t_in !< Input temperature [degC]
339  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: s_in !< Input salinity [ppt]
340  real, intent(in) :: kappa_dt !< A vertical diffusivity to use for smoothing
341  !! times a smoothing timescale [Z2 ~> m2].
342  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(out) :: t_f !< Filled temperature [degC]
343  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(out) :: s_f !< Filled salinity [ppt]
344  integer, optional, intent(in) :: halo_here !< Number of halo points to work on,
345  !! 0 by default
346  logical, optional, intent(in) :: larger_h_denom !< Present and true, add a large
347  !! enough minimal thickness in the denominator of
348  !! the flux calculations so that the fluxes are
349  !! never so large as eliminate the transmission
350  !! of information across groups of massless layers.
351  ! Local variables
352  real :: ent(szi_(g),szk_(g)+1) ! The diffusive entrainment (kappa*dt)/dz
353  ! between layers in a timestep [H ~> m or kg m-2].
354  real :: b1(szi_(g)), d1(szi_(g)) ! b1, c1, and d1 are variables used by the
355  real :: c1(szi_(g),szk_(g)) ! tridiagonal solver.
356  real :: kap_dt_x2 ! The 2*kappa_dt converted to H units [H2 ~> m2 or kg2 m-4].
357  real :: h_neglect ! A negligible thickness [H ~> m or kg m-2], to allow for zero thicknesses.
358  real :: h0 ! A negligible thickness to allow for zero thickness layers without
359  ! completely decouping groups of layers [H ~> m or kg m-2].
360  ! Often 0 < h_neglect << h0.
361  real :: h_tr ! h_tr is h at tracer points with a tiny thickness
362  ! added to ensure positive definiteness [H ~> m or kg m-2].
363  integer :: i, j, k, is, ie, js, je, nz, halo
364 
365  halo=0 ; if (present(halo_here)) halo = max(halo_here,0)
366 
367  is = g%isc-halo ; ie = g%iec+halo ; js = g%jsc-halo ; je = g%jec+halo ; nz = gv%ke
368 
369  h_neglect = gv%H_subroundoff
370  kap_dt_x2 = (2.0*kappa_dt)*gv%Z_to_H**2
371  h0 = h_neglect
372  if (present(larger_h_denom)) then
373  if (larger_h_denom) h0 = 1.0e-16*sqrt(kappa_dt)*gv%Z_to_H
374  endif
375 
376  if (kap_dt_x2 <= 0.0) then
377  !$OMP parallel do default(shared)
378  do k=1,nz ; do j=js,je ; do i=is,ie
379  t_f(i,j,k) = t_in(i,j,k) ; s_f(i,j,k) = s_in(i,j,k)
380  enddo ; enddo ; enddo
381  else
382  !$OMP parallel do default(shared) private(ent,b1,d1,c1,h_tr)
383  do j=js,je
384  do i=is,ie
385  ent(i,2) = kap_dt_x2 / ((h(i,j,1)+h(i,j,2)) + h0)
386  h_tr = h(i,j,1) + h_neglect
387  b1(i) = 1.0 / (h_tr + ent(i,2))
388  d1(i) = b1(i) * h_tr
389  t_f(i,j,1) = (b1(i)*h_tr)*t_in(i,j,1)
390  s_f(i,j,1) = (b1(i)*h_tr)*s_in(i,j,1)
391  enddo
392  do k=2,nz-1 ; do i=is,ie
393  ent(i,k+1) = kap_dt_x2 / ((h(i,j,k)+h(i,j,k+1)) + h0)
394  h_tr = h(i,j,k) + h_neglect
395  c1(i,k) = ent(i,k) * b1(i)
396  b1(i) = 1.0 / ((h_tr + d1(i)*ent(i,k)) + ent(i,k+1))
397  d1(i) = b1(i) * (h_tr + d1(i)*ent(i,k))
398  t_f(i,j,k) = b1(i) * (h_tr*t_in(i,j,k) + ent(i,k)*t_f(i,j,k-1))
399  s_f(i,j,k) = b1(i) * (h_tr*s_in(i,j,k) + ent(i,k)*s_f(i,j,k-1))
400  enddo ; enddo
401  do i=is,ie
402  c1(i,nz) = ent(i,nz) * b1(i)
403  h_tr = h(i,j,nz) + h_neglect
404  b1(i) = 1.0 / (h_tr + d1(i)*ent(i,nz))
405  t_f(i,j,nz) = b1(i) * (h_tr*t_in(i,j,nz) + ent(i,nz)*t_f(i,j,nz-1))
406  s_f(i,j,nz) = b1(i) * (h_tr*s_in(i,j,nz) + ent(i,nz)*s_f(i,j,nz-1))
407  enddo
408  do k=nz-1,1,-1 ; do i=is,ie
409  t_f(i,j,k) = t_f(i,j,k) + c1(i,k+1)*t_f(i,j,k+1)
410  s_f(i,j,k) = s_f(i,j,k) + c1(i,k+1)*s_f(i,j,k+1)
411  enddo ; enddo
412  enddo
413  endif
414 
415 end subroutine vert_fill_ts
416 
417 end module mom_isopycnal_slopes
mom_verticalgrid
Provides a transparent vertical ocean grid type and supporting routines.
Definition: MOM_verticalGrid.F90:2
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_unit_scaling::unit_scale_type
Describes various unit conversion factors.
Definition: MOM_unit_scaling.F90:14
mom_isopycnal_slopes
Calculations of isoneutral slopes and stratification.
Definition: MOM_isopycnal_slopes.F90:2
mom_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.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_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:25