MOM6
MOM_bkgnd_mixing.F90
1 !> Interface to background mixing schemes, including the Bryan and Lewis (1979)
2 !! which is applied via CVMix.
3 
5 
6 ! This file is part of MOM6. See LICENSE.md for the license.
7 
8 use mom_debugging, only : hchksum
9 use mom_diag_mediator, only : diag_ctrl, time_type, register_diag_field
10 use mom_diag_mediator, only : post_data
12 use mom_error_handler, only : mom_error, fatal, warning, note
14 use mom_file_parser, only : openparameterblock, closeparameterblock
15 use mom_forcing_type, only : forcing
16 use mom_grid, only : ocean_grid_type
20 use mom_intrinsic_functions, only : invcosh
21 use cvmix_background, only : cvmix_init_bkgnd, cvmix_coeffs_bkgnd
22 
23 implicit none ; private
24 
25 #include <MOM_memory.h>
26 
27 public bkgnd_mixing_init
28 public bkgnd_mixing_end
29 public calculate_bkgnd_mixing
30 
31 ! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
32 ! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
33 ! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
34 ! vary with the Boussinesq approximation, the Boussinesq variant is given first.
35 
36 !> Control structure including parameters for this module.
37 type, public :: bkgnd_mixing_cs ; private
38 
39  ! Parameters
40  real :: bryan_lewis_c1 !< The vertical diffusivity values for Bryan-Lewis profile
41  !! at |z|=D [m2 s-1]
42  real :: bryan_lewis_c2 !< The amplitude of variation in diffusivity for the
43  !! Bryan-Lewis diffusivity profile [m2 s-1]
44  real :: bryan_lewis_c3 !< The inverse length scale for transition region in the
45  !! Bryan-Lewis diffusivity profile [m-1]
46  real :: bryan_lewis_c4 !< The depth where diffusivity is Bryan_Lewis_bl1 in the
47  !! Bryan-Lewis profile [m]
48  real :: bckgrnd_vdc1 !< Background diffusivity (Ledwell) when
49  !! horiz_varying_background=.true. [Z2 T-1 ~> m2 s-1]
50  real :: bckgrnd_vdc_eq !< Equatorial diffusivity (Gregg) when
51  !! horiz_varying_background=.true. [Z2 T-1 ~> m2 s-1]
52  real :: bckgrnd_vdc_psim !< Max. PSI induced diffusivity (MacKinnon) when
53  !! horiz_varying_background=.true. [Z2 T-1 ~> m2 s-1]
54  real :: bckgrnd_vdc_banda !< Banda Sea diffusivity (Gordon) when
55  !! horiz_varying_background=.true. [Z2 T-1 ~> m2 s-1]
56  real :: kd_min !< minimum diapycnal diffusivity [Z2 T-1 ~> m2 s-1]
57  real :: kd !< interior diapycnal diffusivity [Z2 T-1 ~> m2 s-1]
58  real :: omega !< The Earth's rotation rate [T-1 ~> s-1].
59  real :: n0_2omega !< ratio of the typical Buoyancy frequency to
60  !! twice the Earth's rotation period, used with the
61  !! Henyey scaling from the mixing
62  real :: prandtl_bkgnd !< Turbulent Prandtl number used to convert
63  !! vertical background diffusivity into viscosity
64  real :: kd_tanh_lat_scale !< A nondimensional scaling for the range of
65  !! diffusivities with Kd_tanh_lat_fn. Valid values
66  !! are in the range of -2 to 2; 0.4 reproduces CM2M.
67  real :: kdml !< mixed layer diapycnal diffusivity [Z2 T-1 ~> m2 s-1]
68  !! when bulkmixedlayer==.false.
69  real :: hmix !< mixed layer thickness [Z ~> m] when bulkmixedlayer==.false.
70  logical :: kd_tanh_lat_fn !< If true, use the tanh dependence of Kd_sfc on
71  !! latitude, like GFDL CM2.1/CM2M. There is no
72  !! physical justification for this form, and it can
73  !! not be used with Henyey_IGW_background.
74  logical :: bryan_lewis_diffusivity!< If true, background vertical diffusivity
75  !! uses Bryan-Lewis (1979) like tanh profile.
76  logical :: horiz_varying_background !< If true, apply vertically uniform, latitude-dependent
77  !! background diffusivity, as described in Danabasoglu et al., 2012
78  logical :: henyey_igw_background !< If true, use a simplified variant of the
79  !! Henyey et al, JGR (1986) latitudinal scaling for the background diapycnal diffusivity,
80  !! which gives a marked decrease in the diffusivity near the equator. The simplification
81  !! here is to assume that the in-situ stratification is the same as the reference stratificaiton.
82  logical :: henyey_igw_background_new !< same as Henyey_IGW_background
83  !! but incorporate the effect of stratification on TKE dissipation,
84  !! e = f/f_0 * acosh(N/f) / acosh(N_0/f_0) * e_0
85  !! where e is the TKE dissipation, and N_0 and f_0
86  !! are the reference buoyancy frequency and inertial frequencies respectively.
87  !! e_0 is the reference dissipation at (N_0,f_0). In the previous version, N=N_0.
88  !! Additionally, the squared inverse relationship between diapycnal diffusivities
89  !! and stratification is included:
90  !!
91  !! kd = e/N^2
92  !!
93  !! where kd is the diapycnal diffusivity. This approach assumes that work done
94  !! against gravity is uniformly distributed throughout the column. Whereas, kd=kd_0*e,
95  !! as in the original version, concentrates buoyancy work in regions of strong stratification.
96  logical :: bulkmixedlayer !< If true, a refined bulk mixed layer scheme is used
97  logical :: kd_via_kdml_bug !< If true and KDML /= KD and a number of other higher precedence
98  !! options are not used, the background diffusivity is set incorrectly using a
99  !! bug that was introduced in March, 2018.
100  logical :: debug !< If true, turn on debugging in this module
101  ! Diagnostic handles and pointers
102  type(diag_ctrl), pointer :: diag => null() !< A structure that regulates diagnostic output
103 
104  character(len=40) :: bkgnd_scheme_str = "none" !< Background scheme identifier
105 
106 end type bkgnd_mixing_cs
107 
108 character(len=40) :: mdl = "MOM_bkgnd_mixing" !< This module's name.
109 
110 contains
111 
112 !> Initialize the background mixing routine.
113 subroutine bkgnd_mixing_init(Time, G, GV, US, param_file, diag, CS)
115  type(time_type), intent(in) :: Time !< The current time.
116  type(ocean_grid_type), intent(in) :: G !< Grid structure.
117  type(verticalgrid_type), intent(in) :: GV !< Vertical grid structure.
118  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
119  type(param_file_type), intent(in) :: param_file !< Run-time parameter file handle
120  type(diag_ctrl), target, intent(inout) :: diag !< Diagnostics control structure.
121  type(bkgnd_mixing_cs), pointer :: CS !< This module's control structure.
122 
123  ! Local variables
124  real :: Kv ! The interior vertical viscosity [Z2 T-1 ~> m2 s-1] - read to set Prandtl
125  ! number unless it is provided as a parameter
126  real :: prandtl_bkgnd_comp ! Kv/CS%Kd. Gets compared with user-specified prandtl_bkgnd.
127 
128 ! This include declares and sets the variable "version".
129 #include "version_variable.h"
130 
131  if (associated(cs)) then
132  call mom_error(warning, "bkgnd_mixing_init called with an associated "// &
133  "control structure.")
134  return
135  endif
136  allocate(cs)
137 
138  ! Read parameters
139  call log_version(param_file, mdl, version, &
140  "Adding static vertical background mixing coefficients")
141 
142  call get_param(param_file, mdl, "KD", cs%Kd, &
143  "The background diapycnal diffusivity of density in the "//&
144  "interior. Zero or the molecular value, ~1e-7 m2 s-1, "//&
145  "may be used.", default=0.0, units="m2 s-1", scale=us%m2_s_to_Z2_T)
146 
147  call get_param(param_file, mdl, "KV", kv, &
148  "The background kinematic viscosity in the interior. "//&
149  "The molecular value, ~1e-6 m2 s-1, may be used.", &
150  units="m2 s-1", scale=us%m2_s_to_Z2_T, fail_if_missing=.true.)
151 
152  call get_param(param_file, mdl, "KD_MIN", cs%Kd_min, &
153  "The minimum diapycnal diffusivity.", &
154  units="m2 s-1", default=0.01*cs%Kd*us%Z2_T_to_m2_s, scale=us%m2_s_to_Z2_T)
155 
156  ! The following is needed to set one of the choices of vertical background mixing
157 
158  ! BULKMIXEDLAYER is not always defined (e.g., CM2G63L), so the following line by passes
159  ! the need to include BULKMIXEDLAYER in MOM_input
160  cs%bulkmixedlayer = (gv%nkml > 0)
161  if (cs%bulkmixedlayer) then
162  ! Check that Kdml is not set when using bulk mixed layer
163  call get_param(param_file, mdl, "KDML", cs%Kdml, default=-1.)
164  if (cs%Kdml>0.) call mom_error(fatal, &
165  "bkgnd_mixing_init: KDML cannot be set when using bulk mixed layer.")
166  cs%Kdml = cs%Kd ! This is not used with a bulk mixed layer, but also cannot be a NaN.
167  else
168  call get_param(param_file, mdl, "KDML", cs%Kdml, &
169  "If BULKMIXEDLAYER is false, KDML is the elevated "//&
170  "diapycnal diffusivity in the topmost HMIX of fluid. "//&
171  "KDML is only used if BULKMIXEDLAYER is false.", &
172  units="m2 s-1", default=cs%Kd*us%Z2_T_to_m2_s, scale=us%m2_s_to_Z2_T)
173  call get_param(param_file, mdl, "HMIX_FIXED", cs%Hmix, &
174  "The prescribed depth over which the near-surface "//&
175  "viscosity and diffusivity are elevated when the bulk "//&
176  "mixed layer is not used.", units="m", scale=us%m_to_Z, fail_if_missing=.true.)
177  endif
178 
179  call get_param(param_file, mdl, 'DEBUG', cs%debug, default=.false., do_not_log=.true.)
180 
181 ! call openParameterBlock(param_file,'MOM_BACKGROUND_MIXING')
182 
183  call get_param(param_file, mdl, "BRYAN_LEWIS_DIFFUSIVITY", cs%Bryan_Lewis_diffusivity, &
184  "If true, use a Bryan & Lewis (JGR 1979) like tanh "//&
185  "profile of background diapycnal diffusivity with depth. "//&
186  "This is done via CVMix.", default=.false.)
187 
188  if (cs%Bryan_Lewis_diffusivity) then
189  call check_bkgnd_scheme(cs, "BRYAN_LEWIS_DIFFUSIVITY")
190 
191  call get_param(param_file, mdl, "BRYAN_LEWIS_C1", cs%Bryan_Lewis_c1, &
192  "The vertical diffusivity values for Bryan-Lewis profile at |z|=D.", &
193  units="m2 s-1", fail_if_missing=.true.)
194 
195  call get_param(param_file, mdl, "BRYAN_LEWIS_C2", cs%Bryan_Lewis_c2, &
196  "The amplitude of variation in diffusivity for the Bryan-Lewis profile", &
197  units="m2 s-1", fail_if_missing=.true.)
198 
199  call get_param(param_file, mdl, "BRYAN_LEWIS_C3", cs%Bryan_Lewis_c3, &
200  "The inverse length scale for transition region in the Bryan-Lewis profile", &
201  units="m-1", fail_if_missing=.true.)
202 
203  call get_param(param_file, mdl, "BRYAN_LEWIS_C4", cs%Bryan_Lewis_c4, &
204  "The depth where diffusivity is BRYAN_LEWIS_C1 in the Bryan-Lewis profile",&
205  units="m", fail_if_missing=.true.)
206 
207  endif ! CS%Bryan_Lewis_diffusivity
208 
209  call get_param(param_file, mdl, "HORIZ_VARYING_BACKGROUND", cs%horiz_varying_background, &
210  "If true, apply vertically uniform, latitude-dependent background "//&
211  "diffusivity, as described in Danabasoglu et al., 2012", &
212  default=.false.)
213 
214  if (cs%horiz_varying_background) then
215  call check_bkgnd_scheme(cs, "HORIZ_VARYING_BACKGROUND")
216 
217  call get_param(param_file, mdl, "BCKGRND_VDC1", cs%bckgrnd_vdc1, &
218  "Background diffusivity (Ledwell) when HORIZ_VARYING_BACKGROUND=True", &
219  units="m2 s-1",default = 0.16e-04, scale=us%m2_s_to_Z2_T)
220 
221  call get_param(param_file, mdl, "BCKGRND_VDC_EQ", cs%bckgrnd_vdc_eq, &
222  "Equatorial diffusivity (Gregg) when HORIZ_VARYING_BACKGROUND=True", &
223  units="m2 s-1",default = 0.01e-04, scale=us%m2_s_to_Z2_T)
224 
225  call get_param(param_file, mdl, "BCKGRND_VDC_PSIM", cs%bckgrnd_vdc_psim, &
226  "Max. PSI induced diffusivity (MacKinnon) when HORIZ_VARYING_BACKGROUND=True", &
227  units="m2 s-1",default = 0.13e-4, scale=us%m2_s_to_Z2_T)
228 
229  call get_param(param_file, mdl, "BCKGRND_VDC_BAN", cs%bckgrnd_vdc_Banda, &
230  "Banda Sea diffusivity (Gordon) when HORIZ_VARYING_BACKGROUND=True", &
231  units="m2 s-1",default = 1.0e-4, scale=us%m2_s_to_Z2_T)
232  endif
233 
234  call get_param(param_file, mdl, "PRANDTL_BKGND", cs%prandtl_bkgnd, &
235  "Turbulent Prandtl number used to convert vertical "//&
236  "background diffusivities into viscosities.", &
237  units="nondim", default=1.0)
238 
239  if (cs%Bryan_Lewis_diffusivity .or. cs%horiz_varying_background) then
240 
241  prandtl_bkgnd_comp = cs%prandtl_bkgnd
242  if (cs%Kd /= 0.0) prandtl_bkgnd_comp = kv/cs%Kd
243 
244  if ( abs(cs%prandtl_bkgnd - prandtl_bkgnd_comp)>1.e-14) then
245  call mom_error(fatal,"set_diffusivity_init: The provided KD, KV,"//&
246  "and PRANDTL_BKGND values are incompatible. The following "//&
247  "must hold: KD*PRANDTL_BKGND==KV")
248  endif
249 
250  endif
251 
252  call get_param(param_file, mdl, "HENYEY_IGW_BACKGROUND", cs%Henyey_IGW_background, &
253  "If true, use a latitude-dependent scaling for the near "//&
254  "surface background diffusivity, as described in "//&
255  "Harrison & Hallberg, JPO 2008.", default=.false.)
256  if (cs%Henyey_IGW_background) call check_bkgnd_scheme(cs, "HENYEY_IGW_BACKGROUND")
257 
258 
259  call get_param(param_file, mdl, "HENYEY_IGW_BACKGROUND_NEW", cs%Henyey_IGW_background_new, &
260  "If true, use a better latitude-dependent scaling for the "//&
261  "background diffusivity, as described in "//&
262  "Harrison & Hallberg, JPO 2008.", default=.false.)
263  if (cs%Henyey_IGW_background_new) call check_bkgnd_scheme(cs, "HENYEY_IGW_BACKGROUND_NEW")
264 
265  if (cs%Kd>0.0 .and. (trim(cs%bkgnd_scheme_str)=="BRYAN_LEWIS_DIFFUSIVITY" .or.&
266  trim(cs%bkgnd_scheme_str)=="HORIZ_VARYING_BACKGROUND" )) then
267  call mom_error(warning, "set_diffusivity_init: a nonzero constant background "//&
268  "diffusivity (KD) is specified along with "//trim(cs%bkgnd_scheme_str))
269  endif
270 
271  if (cs%Henyey_IGW_background) then
272  call get_param(param_file, mdl, "HENYEY_N0_2OMEGA", cs%N0_2Omega, &
273  "The ratio of the typical Buoyancy frequency to twice "//&
274  "the Earth's rotation period, used with the Henyey "//&
275  "scaling from the mixing.", units="nondim", default=20.0)
276  call get_param(param_file, mdl, "OMEGA", cs%omega, &
277  "The rotation rate of the earth.", units="s-1", &
278  default=7.2921e-5, scale=us%T_to_s)
279  endif
280 
281  call get_param(param_file, mdl, "KD_TANH_LAT_FN", cs%Kd_tanh_lat_fn, &
282  "If true, use a tanh dependence of Kd_sfc on latitude, "//&
283  "like CM2.1/CM2M. There is no physical justification "//&
284  "for this form, and it can not be used with "//&
285  "HENYEY_IGW_BACKGROUND.", default=.false.)
286 
287  if (cs%Kd_tanh_lat_fn) &
288  call get_param(param_file, mdl, "KD_TANH_LAT_SCALE", cs%Kd_tanh_lat_scale, &
289  "A nondimensional scaling for the range ofdiffusivities "//&
290  "with KD_TANH_LAT_FN. Valid values are in the range of "//&
291  "-2 to 2; 0.4 reproduces CM2M.", units="nondim", default=0.0)
292 
293  if (cs%Henyey_IGW_background .and. cs%Kd_tanh_lat_fn) call mom_error(fatal, &
294  "MOM_bkgnd_mixing: KD_TANH_LAT_FN can not be used with HENYEY_IGW_BACKGROUND.")
295 
296  cs%Kd_via_Kdml_bug = .false.
297  if ((cs%Kd /= cs%Kdml) .and. .not.(cs%Kd_tanh_lat_fn .or. cs%bulkmixedlayer .or. &
298  cs%Henyey_IGW_background .or. cs%Henyey_IGW_background_new .or. &
299  cs%horiz_varying_background .or. cs%Bryan_Lewis_diffusivity)) then
300  call get_param(param_file, mdl, "KD_BACKGROUND_VIA_KDML_BUG", cs%Kd_via_Kdml_bug, &
301  "If true and KDML /= KD and several other conditions apply, the background "//&
302  "diffusivity is set incorrectly using a bug that was introduced in March, 2018.", &
303  default=.true.) ! The default should be changed to false and this parameter obsoleted.
304  endif
305 
306 ! call closeParameterBlock(param_file)
307 
308 end subroutine bkgnd_mixing_init
309 
310 !> Calculates the vertical background diffusivities/viscosities
311 subroutine calculate_bkgnd_mixing(h, tv, N2_lay, Kd_lay, Kd_int, Kv_bkgnd, j, G, GV, US, CS)
313  type(ocean_grid_type), intent(in) :: G !< Grid structure.
314  type(verticalgrid_type), intent(in) :: GV !< Vertical grid structure.
315  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2].
316  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamics structure.
317  real, dimension(SZI_(G),SZK_(GV)), intent(in) :: N2_lay !< squared buoyancy frequency associated
318  !! with layers [T-2 ~> s-2]
319  real, dimension(SZI_(G),SZK_(GV)), intent(out) :: Kd_lay !< The background diapycnal diffusivity
320  !! of each layer [Z2 T-1 ~> m2 s-1].
321  real, dimension(SZI_(G),SZK_(GV)+1), intent(out) :: Kd_int !< The background diapycnal diffusivity
322  !! of each interface [Z2 T-1 ~> m2 s-1].
323  real, dimension(SZI_(G),SZK_(GV)+1), intent(out) :: Kv_bkgnd !< The background vertical viscosity at
324  !! each interface [Z2 T-1 ~> m2 s-1]
325  integer, intent(in) :: j !< Meridional grid index
326  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
327  type(bkgnd_mixing_cs), pointer :: CS !< The control structure returned by
328  !! a previous call to bkgnd_mixing_init.
329 
330  ! local variables
331  real, dimension(SZK_(GV)+1) :: depth_int !< Distance from surface of the interfaces [m]
332  real, dimension(SZK_(GV)+1) :: Kd_col !< Diffusivities at the interfaces [m2 s-1]
333  real, dimension(SZK_(GV)+1) :: Kv_col !< Viscosities at the interfaces [m2 s-1]
334  real, dimension(SZI_(G)) :: Kd_sfc !< Surface value of the diffusivity [Z2 T-1 ~> m2 s-1]
335  real, dimension(SZI_(G)) :: depth !< Distance from surface of an interface [Z ~> m]
336  real :: depth_c !< depth of the center of a layer [Z ~> m]
337  real :: I_Hmix !< inverse of fixed mixed layer thickness [Z-1 ~> m-1]
338  real :: I_2Omega !< 1/(2 Omega) [T ~> s]
339  real :: N_2Omega ! The ratio of the stratification to the Earth's rotation rate [nondim]
340  real :: N02_N2 ! The ratio a reference stratification to the actual stratification [nondim]
341  real :: I_x30 !< 2/acos(2) = 1/(sin(30 deg) * acosh(1/sin(30 deg)))
342  real :: deg_to_rad !< factor converting degrees to radians, pi/180.
343  real :: abs_sinlat !< absolute value of sine of latitude [nondim]
344  real :: min_sinlat ! The minimum value of the sine of latitude [nondim]
345  real :: bckgrnd_vdc_psin !< PSI diffusivity in northern hemisphere [Z2 T-1 ~> m2 s-1]
346  real :: bckgrnd_vdc_psis !< PSI diffusivity in southern hemisphere [Z2 T-1 ~> m2 s-1]
347  integer :: i, k, is, ie, js, je, nz
348 
349  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
350 
351  ! set some parameters
352  deg_to_rad = atan(1.0)/45.0 ! = PI/180
353  min_sinlat = 1.e-10
354 
355  ! Start with a constant value that may be replaced below.
356  kd_lay(:,:) = cs%Kd
357  kv_bkgnd(:,:) = 0.0
358 
359  ! Set up the background diffusivity.
360  if (cs%Bryan_Lewis_diffusivity) then
361 
362  do i=is,ie
363  depth_int(1) = 0.0
364  do k=2,nz+1
365  depth_int(k) = depth_int(k-1) + gv%H_to_m*h(i,j,k-1)
366  enddo
367 
368  call cvmix_init_bkgnd(max_nlev=nz, &
369  zw = depth_int(:), & !< interface depths relative to the surface in m, must be positive.
370  bl1 = cs%Bryan_Lewis_c1, &
371  bl2 = cs%Bryan_Lewis_c2, &
372  bl3 = cs%Bryan_Lewis_c3, &
373  bl4 = cs%Bryan_Lewis_c4, &
374  prandtl = cs%prandtl_bkgnd)
375 
376  kd_col(:) = 0.0 ; kv_col(:) = 0.0 ! Is this line necessary?
377  call cvmix_coeffs_bkgnd(mdiff_out=kv_col, tdiff_out=kd_col, nlev=nz, max_nlev=nz)
378 
379  ! Update Kd and Kv.
380  do k=1,nz+1
381  kv_bkgnd(i,k) = us%m2_s_to_Z2_T*kv_col(k)
382  kd_int(i,k) = us%m2_s_to_Z2_T*kd_col(k)
383  enddo
384  do k=1,nz
385  kd_lay(i,k) = kd_lay(i,k) + 0.5 * us%m2_s_to_Z2_T * (kd_col(k) + kd_col(k+1))
386  enddo
387  enddo ! i loop
388 
389  elseif (cs%horiz_varying_background) then
390  !### Note that there are lots of hard-coded parameters (mostly latitudes and longitudes) here.
391  do i=is,ie
392  bckgrnd_vdc_psis = cs%bckgrnd_vdc_psim * exp(-(0.4*(g%geoLatT(i,j)+28.9))**2)
393  bckgrnd_vdc_psin = cs%bckgrnd_vdc_psim * exp(-(0.4*(g%geoLatT(i,j)-28.9))**2)
394  kd_int(i,1) = (cs%bckgrnd_vdc_eq + bckgrnd_vdc_psin) + bckgrnd_vdc_psis
395 
396  if (g%geoLatT(i,j) < -10.0) then
397  kd_int(i,1) = kd_int(i,1) + cs%bckgrnd_vdc1
398  elseif (g%geoLatT(i,j) <= 10.0) then
399  kd_int(i,1) = kd_int(i,1) + cs%bckgrnd_vdc1 * (g%geoLatT(i,j)/10.0)**2
400  else
401  kd_int(i,1) = kd_int(i,1) + cs%bckgrnd_vdc1
402  endif
403 
404  ! North Banda Sea
405  if ( (g%geoLatT(i,j) < -1.0) .and. (g%geoLatT(i,j) > -4.0) .and. &
406  ( mod(g%geoLonT(i,j)+360.0,360.0) > 103.0) .and. &
407  ( mod(g%geoLonT(i,j)+360.0,360.0) < 134.0) ) then
408  kd_int(i,1) = cs%bckgrnd_vdc_Banda
409  endif
410 
411  ! Middle Banda Sea
412  if ( (g%geoLatT(i,j) <= -4.0) .and. (g%geoLatT(i,j) > -7.0) .and. &
413  ( mod(g%geoLonT(i,j)+360.0,360.0) > 106.0) .and. &
414  ( mod(g%geoLonT(i,j)+360.0,360.0) < 140.0) ) then
415  kd_int(i,1) = cs%bckgrnd_vdc_Banda
416  endif
417 
418  ! South Banda Sea
419  if ( (g%geoLatT(i,j) <= -7.0) .and. (g%geoLatT(i,j) > -8.3) .and. &
420  ( mod(g%geoLonT(i,j)+360.0,360.0) > 111.0) .and. &
421  ( mod(g%geoLonT(i,j)+360.0,360.0) < 142.0) ) then
422  kd_int(i,1) = cs%bckgrnd_vdc_Banda
423  endif
424 
425  enddo
426  ! Update interior values of Kd and Kv (uniform profile; no interpolation needed)
427  do k=1,nz+1 ; do i=is,ie
428  kd_int(i,k) = kd_int(i,1)
429  kv_bkgnd(i,k) = kd_int(i,1) * cs%prandtl_bkgnd
430  enddo ; enddo
431  do k=1,nz ; do i=is,ie
432  kd_lay(i,k) = kd_int(i,1)
433  enddo ; enddo
434 
435  elseif (cs%Henyey_IGW_background_new) then
436  i_x30 = 2.0 / invcosh(cs%N0_2Omega*2.0) ! This is evaluated at 30 deg.
437  i_2omega = 0.5 / cs%omega
438  do k=1,nz ; do i=is,ie
439  abs_sinlat = max(min_sinlat, abs(sin(g%geoLatT(i,j)*deg_to_rad)))
440  n_2omega = max(abs_sinlat, sqrt(n2_lay(i,k))*i_2omega)
441  n02_n2 = (cs%N0_2Omega/n_2omega)**2
442  kd_lay(i,k) = max(cs%Kd_min, cs%Kd * &
443  ((abs_sinlat * invcosh(n_2omega/abs_sinlat)) * i_x30)*n02_n2)
444  enddo ; enddo
445  ! Update Kd_int and Kv_bkgnd, based on Kd_lay. These might be just used for diagnostic purposes.
446  do i=is,ie
447  kd_int(i,1) = 0.0; kv_bkgnd(i,1) = 0.0
448  kd_int(i,nz+1) = 0.0; kv_bkgnd(i,nz+1) = 0.0
449  enddo
450  do k=2,nz ; do i=is,ie
451  kd_int(i,k) = 0.5*(kd_lay(i,k-1) + kd_lay(i,k))
452  kv_bkgnd(i,k) = kd_int(i,k) * cs%prandtl_bkgnd
453  enddo ; enddo
454  else
455  ! Set a potentially spatially varying surface value of diffusivity.
456  if (cs%Henyey_IGW_background) then
457  i_x30 = 2.0 / invcosh(cs%N0_2Omega*2.0) ! This is evaluated at 30 deg.
458  do i=is,ie
459  abs_sinlat = abs(sin(g%geoLatT(i,j)*deg_to_rad))
460  kd_sfc(i) = max(cs%Kd_min, cs%Kd * &
461  ((abs_sinlat * invcosh(cs%N0_2Omega / max(min_sinlat, abs_sinlat))) * i_x30) )
462  enddo
463  elseif (cs%Kd_tanh_lat_fn) then
464  do i=is,ie
465  ! The transition latitude and latitude range are hard-scaled here, since
466  ! this is not really intended for wide-spread use, but rather for
467  ! comparison with CM2M / CM2.1 settings.
468  kd_sfc(i) = max(cs%Kd_min, cs%Kd * (1.0 + &
469  cs%Kd_tanh_lat_scale * 0.5*tanh((abs(g%geoLatT(i,j)) - 35.0)/5.0) ))
470  enddo
471  else ! Use a spatially constant surface value.
472  do i=is,ie
473  kd_sfc(i) = cs%Kd
474  enddo
475  endif
476 
477  ! Now set background diffusivies based on these surface values, possibly with vertical structure.
478  if ((.not.cs%bulkmixedlayer) .and. (cs%Kd /= cs%Kdml)) then
479  ! This is a crude way to put in a diffusive boundary layer without an explicit boundary
480  ! layer turbulence scheme. It should not be used for any realistic ocean models.
481  i_hmix = 1.0 / (cs%Hmix + gv%H_subroundoff*gv%H_to_Z)
482  do i=is,ie ; depth(i) = 0.0 ; enddo
483  do k=1,nz ; do i=is,ie
484  depth_c = depth(i) + 0.5*gv%H_to_Z*h(i,j,k)
485  if (cs%Kd_via_Kdml_bug) then
486  ! These two lines should update Kd_lay, not Kd_int. They were correctly working on the
487  ! same variables until MOM6 commit 7a818716 (PR#750), which was added on March 26, 2018.
488  if (depth_c <= cs%Hmix) then ; kd_int(i,k) = cs%Kdml
489  elseif (depth_c >= 2.0*cs%Hmix) then ; kd_int(i,k) = kd_sfc(i)
490  else
491  kd_lay(i,k) = ((kd_sfc(i) - cs%Kdml) * i_hmix) * depth_c + (2.0*cs%Kdml - kd_sfc(i))
492  endif
493  else
494  if (depth_c <= cs%Hmix) then ; kd_lay(i,k) = cs%Kdml
495  elseif (depth_c >= 2.0*cs%Hmix) then ; kd_lay(i,k) = kd_sfc(i)
496  else
497  kd_lay(i,k) = ((kd_sfc(i) - cs%Kdml) * i_hmix) * depth_c + (2.0*cs%Kdml - kd_sfc(i))
498  endif
499  endif
500 
501  depth(i) = depth(i) + gv%H_to_Z*h(i,j,k)
502  enddo ; enddo
503 
504  else ! There is no vertical structure to the background diffusivity.
505  do k=1,nz ; do i=is,ie
506  kd_lay(i,k) = kd_sfc(i)
507  enddo ; enddo
508  endif
509 
510  ! Update Kd_int and Kv_bkgnd, based on Kd_lay. These might be just used for diagnostic purposes.
511  do i=is,ie
512  kd_int(i,1) = 0.0; kv_bkgnd(i,1) = 0.0
513  kd_int(i,nz+1) = 0.0; kv_bkgnd(i,nz+1) = 0.0
514  enddo
515  do k=2,nz ; do i=is,ie
516  kd_int(i,k) = 0.5*(kd_lay(i,k-1) + kd_lay(i,k))
517  kv_bkgnd(i,k) = kd_int(i,k) * cs%prandtl_bkgnd
518  enddo ; enddo
519  endif
520 
521 end subroutine calculate_bkgnd_mixing
522 
523 !> Reads the parameter "USE_CVMix_BACKGROUND" and returns state.
524 !! This function allows other modules to know whether this parameterization will
525 !! be used without needing to duplicate the log entry.
526 logical function cvmix_bkgnd_is_used(param_file)
527  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
528  call get_param(param_file, mdl, "USE_CVMix_BACKGROUND", cvmix_bkgnd_is_used, &
529  default=.false., do_not_log = .true.)
530 
531 end function cvmix_bkgnd_is_used
532 
533 !> Sets CS%bkgnd_scheme_str to check whether multiple background diffusivity schemes are activated.
534 !! The string is also for error/log messages.
535 subroutine check_bkgnd_scheme(CS, str)
536  type(bkgnd_mixing_cs), pointer :: CS !< Control structure
537  character(len=*), intent(in) :: str !< Background scheme identifier deducted from MOM_input
538  !! parameters
539 
540  if (trim(cs%bkgnd_scheme_str)=="none") then
541  cs%bkgnd_scheme_str = str
542  else
543  call mom_error(fatal, "set_diffusivity_init: Cannot activate both "//trim(str)//" and "//&
544  trim(cs%bkgnd_scheme_str)//".")
545  endif
546 
547 end subroutine
548 
549 !> Clear pointers and dealocate memory
550 subroutine bkgnd_mixing_end(CS)
551  type(bkgnd_mixing_cs), pointer :: CS !< Control structure for this module that
552  !! will be deallocated in this subroutine
553 
554  if (.not. associated(cs)) return
555  deallocate(cs)
556 
557 end subroutine bkgnd_mixing_end
558 
559 
560 end module mom_bkgnd_mixing
This module implements boundary forcing for MOM6.
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:26
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Calculates density of sea water from T, S and P.
Definition: MOM_EOS.F90:68
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
Definition: MOM_grid.F90:2
Vertical viscosities, drag coefficients, and related fields.
Interface to background mixing schemes, including the Bryan and Lewis (1979) which is applied via CVM...
The MOM6 facility to parse input files for runtime parameters.
Make a diagnostic available for averaging or output.
Describes various unit conversion factors.
A module with intrinsic functions that are used by MOM but are not supported by some compilers...
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Routines for error handling and I/O management.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Calculate the derivatives of density with temperature and salinity from T, S, and P...
Definition: MOM_EOS.F90:81
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
An overloaded interface to log version information about modules.
Control structure including parameters for this module.
Describes the vertical ocean grid, including unit conversion factors.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.
An overloaded interface to read and log the values of various types of parameters.
Provides checksumming functions for debugging.