MOM6
MOM_CVMix_conv.F90
1 !> Interface to CVMix convection scheme.
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_debugging, only : hchksum
7 use mom_diag_mediator, only : diag_ctrl, time_type, register_diag_field
9 use mom_eos, only : calculate_density
10 use mom_error_handler, only : mom_error, is_root_pe, fatal, warning, note
11 use mom_file_parser, only : openparameterblock, closeparameterblock
13 use mom_grid, only : ocean_grid_type
17 use cvmix_convection, only : cvmix_init_conv, cvmix_coeffs_conv
18 use cvmix_kpp, only : cvmix_kpp_compute_kobl_depth
19 
20 implicit none ; private
21 
22 #include <MOM_memory.h>
23 
24 public cvmix_conv_init, calculate_cvmix_conv, cvmix_conv_end, cvmix_conv_is_used
25 
26 !> Control structure including parameters for CVMix convection.
27 type, public :: cvmix_conv_cs ; private
28 
29  ! Parameters
30  real :: kd_conv_const !< diffusivity constant used in convective regime [m2 s-1]
31  real :: kv_conv_const !< viscosity constant used in convective regime [m2 s-1]
32  real :: bv_sqr_conv !< Threshold for squared buoyancy frequency
33  !! needed to trigger Brunt-Vaisala parameterization [s-2]
34  real :: min_thickness !< Minimum thickness allowed [m]
35  logical :: debug !< If true, turn on debugging
36 
37  ! Daignostic handles and pointers
38  type(diag_ctrl), pointer :: diag => null() !< Pointer to diagnostics control structure
39  !>@{ Diagnostics handles
40  integer :: id_n2 = -1, id_kd_conv = -1, id_kv_conv = -1
41  !>@}
42 
43 end type cvmix_conv_cs
44 
45 character(len=40) :: mdl = "MOM_CVMix_conv" !< This module's name.
46 
47 contains
48 
49 !> Initialized the CVMix convection mixing routine.
50 logical function cvmix_conv_init(Time, G, GV, US, param_file, diag, CS)
51 
52  type(time_type), intent(in) :: time !< The current time.
53  type(ocean_grid_type), intent(in) :: g !< Grid structure.
54  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure.
55  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
56  type(param_file_type), intent(in) :: param_file !< Run-time parameter file handle
57  type(diag_ctrl), target, intent(inout) :: diag !< Diagnostics control structure.
58  type(cvmix_conv_cs), pointer :: cs !< This module's control structure.
59  ! Local variables
60  real :: prandtl_conv !< Turbulent Prandtl number used in convective instabilities.
61  logical :: useepbl !< If True, use the ePBL boundary layer scheme.
62 
63 ! This include declares and sets the variable "version".
64 #include "version_variable.h"
65 
66  if (associated(cs)) then
67  call mom_error(warning, "CVMix_conv_init called with an associated "// &
68  "control structure.")
69  return
70  endif
71  allocate(cs)
72 
73  ! Read parameters
74  call get_param(param_file, mdl, "USE_CVMix_CONVECTION", cvmix_conv_init, default=.false., do_not_log=.true.)
75  call log_version(param_file, mdl, version, &
76  "Parameterization of enhanced mixing due to convection via CVMix", &
77  all_default=.not.cvmix_conv_init)
78  call get_param(param_file, mdl, "USE_CVMix_CONVECTION", cvmix_conv_init, &
79  "If true, turns on the enhanced mixing due to convection "//&
80  "via CVMix. This scheme increases diapycnal diffs./viscs. "//&
81  "at statically unstable interfaces. Relevant parameters are "//&
82  "contained in the CVMix_CONVECTION% parameter block.", &
83  default=.false.)
84 
85  if (.not. cvmix_conv_init) return
86 
87  call get_param(param_file, mdl, "ENERGETICS_SFC_PBL", useepbl, default=.false., &
88  do_not_log=.true.)
89 
90  ! Warn user if EPBL is being used, since in this case mixing due to convection will
91  ! be aplied in the boundary layer
92  if (useepbl) then
93  call mom_error(warning, 'MOM_CVMix_conv_init: '// &
94  'CVMix convection may not be properly applied when ENERGETICS_SFC_PBL = True'//&
95  'as convective mixing might occur in the boundary layer.')
96  endif
97 
98  call get_param(param_file, mdl, 'DEBUG', cs%debug, default=.false., do_not_log=.true.)
99 
100  call get_param(param_file, mdl, 'MIN_THICKNESS', cs%min_thickness, default=0.001, do_not_log=.true.)
101 
102  call openparameterblock(param_file,'CVMix_CONVECTION')
103 
104  call get_param(param_file, mdl, "PRANDTL_CONV", prandtl_conv, &
105  "The turbulent Prandtl number applied to convective "//&
106  "instabilities (i.e., used to convert KD_CONV into KV_CONV)", &
107  units="nondim", default=1.0)
108 
109  call get_param(param_file, mdl, 'KD_CONV', cs%kd_conv_const, &
110  "Diffusivity used in convective regime. Corresponding viscosity "//&
111  "(KV_CONV) will be set to KD_CONV * PRANDTL_TURB.", &
112  units='m2/s', default=1.00)
113 
114  call get_param(param_file, mdl, 'BV_SQR_CONV', cs%bv_sqr_conv, &
115  "Threshold for squared buoyancy frequency needed to trigger "//&
116  "Brunt-Vaisala parameterization.", &
117  units='1/s^2', default=0.0)
118 
119  call closeparameterblock(param_file)
120 
121  ! set kv_conv_const based on kd_conv_const and prandtl_conv
122  cs%kv_conv_const = cs%kd_conv_const * prandtl_conv
123 
124  ! Register diagnostics
125  cs%diag => diag
126  cs%id_N2 = register_diag_field('ocean_model', 'N2_conv', diag%axesTi, time, &
127  'Square of Brunt-Vaisala frequency used by MOM_CVMix_conv module', '1/s2', conversion=us%s_to_T**2)
128  cs%id_kd_conv = register_diag_field('ocean_model', 'kd_conv', diag%axesTi, time, &
129  'Additional diffusivity added by MOM_CVMix_conv module', 'm2/s', conversion=us%Z2_T_to_m2_s)
130  cs%id_kv_conv = register_diag_field('ocean_model', 'kv_conv', diag%axesTi, time, &
131  'Additional viscosity added by MOM_CVMix_conv module', 'm2/s', conversion=us%Z2_T_to_m2_s)
132 
133  call cvmix_init_conv(convect_diff=cs%kd_conv_const, &
134  convect_visc=cs%kv_conv_const, &
135  lbruntvaisala=.true., &
136  bvsqr_convect=cs%bv_sqr_conv)
137 
138 end function cvmix_conv_init
139 
140 !> Subroutine for calculating enhanced diffusivity/viscosity
141 !! due to convection via CVMix
142 subroutine calculate_cvmix_conv(h, tv, G, GV, US, CS, hbl, Kd, Kv, Kd_aux)
143 
144  type(ocean_grid_type), intent(in) :: g !< Grid structure.
145  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure.
146  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
147  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2].
148  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamics structure.
149  type(cvmix_conv_cs), pointer :: cs !< The control structure returned
150  !! by a previous call to CVMix_conv_init.
151  real, dimension(SZI_(G),SZJ_(G)), intent(in) :: hbl !< Depth of ocean boundary layer [Z ~> m]
152  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
153  optional, intent(inout) :: kd !< Diapycnal diffusivity at each interface that
154  !! will be incremented here [Z2 T-1 ~> m2 s-1].
155  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
156  optional, intent(inout) :: kv !< Viscosity at each interface that will be
157  !! incremented here [Z2 T-1 ~> m2 s-1].
158  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
159  optional, intent(inout) :: kd_aux !< A second diapycnal diffusivity at each
160  !! interface that will also be incremented
161  !! here [Z2 T-1 ~> m2 s-1].
162 
163  ! local variables
164  real, dimension(SZK_(GV)) :: rho_lwr !< Adiabatic Water Density, this is a dummy
165  !! variable since here convection is always
166  !! computed based on Brunt Vaisala.
167  real, dimension(SZK_(GV)) :: rho_1d !< water density in a column, this is also
168  !! a dummy variable, same reason as above.
169  real, dimension(SZK_(GV)+1) :: n2 !< Squared buoyancy frequency [s-2]
170  real, dimension(SZK_(GV)+1) :: kv_col !< Viscosities at interfaces in the column [m2 s-1]
171  real, dimension(SZK_(GV)+1) :: kd_col !< Diffusivities at interfaces in the column [m2 s-1]
172  real, dimension(SZK_(GV)+1) :: ifaceheight !< Height of interfaces [m]
173  real, dimension(SZK_(GV)) :: cellheight !< Height of cell centers [m]
174  real, dimension(SZI_(G),SZJ_(G),SZK_(GV)+1) :: &
175  kd_conv, & !< Diffusivity added by convection for diagnostics [Z2 T-1 ~> m2 s-1]
176  kv_conv, & !< Viscosity added by convection for diagnostics [Z2 T-1 ~> m2 s-1]
177  n2_3d !< Squared buoyancy frequency for diagnostics [N-2 ~> s-2]
178  integer :: kobl !< level of OBL extent
179  real :: g_o_rho0 ! Gravitational acceleration divided by density times unit convserion factors
180  ! [Z s-2 R-1 ~> m4 s-2 kg-1]
181  real :: pref ! Interface pressures [R L2 T-2 ~> Pa]
182  real :: rhok, rhokm1 ! In situ densities of the layers above and below at the interface pressure [R ~> kg m-3]
183  real :: hbl_kpp ! The depth of the ocean boundary as used by KPP [m]
184  real :: dz ! A thickness [Z ~> m]
185  real :: dh, hcorr ! Two thicknesses [m]
186  integer :: i, j, k
187 
188  g_o_rho0 = us%L_to_Z**2*us%s_to_T**2 * gv%g_Earth / gv%Rho0
189 
190  ! initialize dummy variables
191  rho_lwr(:) = 0.0 ; rho_1d(:) = 0.0
192 
193  ! set N2 to zero at the top- and bottom-most interfaces
194  n2(1) = 0.0 ; n2(gv%ke+1) = 0.0
195 
196  if (cs%id_N2 > 0) n2_3d(:,:,:) = 0.0
197  if (cs%id_kv_conv > 0) kv_conv(:,:,:) = 0.0
198  if (cs%id_kd_conv > 0) kd_conv(:,:,:) = 0.0
199 
200  do j = g%jsc, g%jec
201  do i = g%isc, g%iec
202 
203  ! skip calling at land points
204  !if (G%mask2dT(i,j) == 0.) cycle
205 
206  pref = 0. ; if (associated(tv%p_surf)) pref = tv%p_surf(i,j)
207  ! Compute Brunt-Vaisala frequency (static stability) on interfaces
208  do k=2,gv%ke
209 
210  ! pRef is pressure at interface between k and km1 [R L2 T-2 ~> Pa].
211  pref = pref + (gv%H_to_RZ*gv%g_Earth) * h(i,j,k)
212  call calculate_density(tv%t(i,j,k), tv%s(i,j,k), pref, rhok, tv%eqn_of_state)
213  call calculate_density(tv%t(i,j,k-1), tv%s(i,j,k-1), pref, rhokm1, tv%eqn_of_state)
214 
215  dz = ((0.5*(h(i,j,k-1) + h(i,j,k))+gv%H_subroundoff)*gv%H_to_Z)
216  n2(k) = g_o_rho0 * (rhok - rhokm1) / dz ! Can be negative
217 
218  enddo
219 
220  ifaceheight(1) = 0.0 ! BBL is all relative to the surface
221  hcorr = 0.0
222  ! compute heights at cell center and interfaces
223  do k=1,gv%ke
224  dh = h(i,j,k) * gv%H_to_m ! Nominal thickness to use for increment, in the units used by CVMix.
225  dh = dh + hcorr ! Take away the accumulated error (could temporarily make dh<0)
226  hcorr = min( dh - cs%min_thickness, 0. ) ! If inflating then hcorr<0
227  dh = max( dh, cs%min_thickness ) ! Limit increment dh>=min_thickness
228  cellheight(k) = ifaceheight(k) - 0.5 * dh
229  ifaceheight(k+1) = ifaceheight(k) - dh
230  enddo
231 
232  ! gets index of the level and interface above hbl
233  hbl_kpp = us%Z_to_m*hbl(i,j) ! Convert to the units used by CVMix.
234  kobl = cvmix_kpp_compute_kobl_depth(ifaceheight, cellheight, hbl_kpp)
235 
236  kv_col(:) = 0.0 ; kd_col(:) = 0.0
237  call cvmix_coeffs_conv(mdiff_out=kv_col(:), &
238  tdiff_out=kd_col(:), &
239  nsqr=n2(:), &
240  dens=rho_1d(:), &
241  dens_lwr=rho_lwr(:), &
242  nlev=gv%ke, &
243  max_nlev=gv%ke, &
244  obl_ind=kobl)
245 
246  if (present(kd)) then
247  ! Increment the diffusivity outside of the boundary layer.
248  do k=max(1,kobl+1),gv%ke+1
249  kd(i,j,k) = kd(i,j,k) + us%m2_s_to_Z2_T * kd_col(k)
250  enddo
251  endif
252  if (present(kd_aux)) then
253  ! Increment the other diffusivity outside of the boundary layer.
254  do k=max(1,kobl+1),gv%ke+1
255  kd_aux(i,j,k) = kd_aux(i,j,k) + us%m2_s_to_Z2_T * kd_col(k)
256  enddo
257  endif
258 
259  if (present(kv)) then
260  ! Increment the viscosity outside of the boundary layer.
261  do k=max(1,kobl+1),gv%ke+1
262  kv(i,j,k) = kv(i,j,k) + us%m2_s_to_Z2_T * kv_col(k)
263  enddo
264  endif
265 
266  ! Store 3-d arrays for diagnostics.
267  if (cs%id_kv_conv > 0) then
268  ! Do not apply mixing due to convection within the boundary layer
269  do k=max(1,kobl+1),gv%ke+1
270  kv_conv(i,j,k) = us%m2_s_to_Z2_T * kv_col(k)
271  enddo
272  endif
273  if (cs%id_kd_conv > 0) then
274  ! Do not apply mixing due to convection within the boundary layer
275  do k=max(1,kobl+1),gv%ke+1
276  kd_conv(i,j,k) = us%m2_s_to_Z2_T * kd_col(k)
277  enddo
278  endif
279 
280  if (cs%id_N2 > 0) then ; do k=2,gv%ke ; n2_3d(i,j,k) = us%T_to_s**2*n2(k) ; enddo ; endif
281 
282  enddo
283  enddo
284 
285  if (cs%debug) then
286  ! if (CS%id_N2 > 0) call hchksum(N2_3d, "MOM_CVMix_conv: N2",G%HI,haloshift=0)
287  ! if (CS%id_kd_conv > 0) &
288  ! call hchksum(Kd_conv, "MOM_CVMix_conv: Kd_conv", G%HI, haloshift=0, scale=US%Z2_T_to_m2_s)
289  ! if (CS%id_kv_conv > 0) &
290  ! call hchksum(Kv_conv, "MOM_CVMix_conv: Kv_conv", G%HI, haloshift=0, scale=US%m2_s_to_Z2_T)
291  if (present(kd)) call hchksum(kv, "MOM_CVMix_conv: Kd", g%HI, haloshift=0, scale=us%m2_s_to_Z2_T)
292  if (present(kv)) call hchksum(kv, "MOM_CVMix_conv: Kv", g%HI, haloshift=0, scale=us%m2_s_to_Z2_T)
293  endif
294 
295  ! send diagnostics to post_data
296  if (cs%id_N2 > 0) call post_data(cs%id_N2, n2_3d, cs%diag)
297  if (cs%id_kd_conv > 0) call post_data(cs%id_kd_conv, kd_conv, cs%diag)
298  if (cs%id_kv_conv > 0) call post_data(cs%id_kv_conv, kv_conv, cs%diag)
299 
300 end subroutine calculate_cvmix_conv
301 
302 !> Reads the parameter "USE_CVMix_CONVECTION" and returns state.
303 !! This function allows other modules to know whether this parameterization will
304 !! be used without needing to duplicate the log entry.
305 logical function cvmix_conv_is_used(param_file)
306  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
307  call get_param(param_file, mdl, "USE_CVMix_CONVECTION", cvmix_conv_is_used, &
308  default=.false., do_not_log = .true.)
309 
310 end function cvmix_conv_is_used
311 
312 !> Clear pointers and dealocate memory
313 subroutine cvmix_conv_end(CS)
314  type(cvmix_conv_cs), pointer :: cs !< Control structure for this module that
315  !! will be deallocated in this subroutine
316 
317  if (.not. associated(cs)) return
318 
319  deallocate(cs)
320 
321 end subroutine cvmix_conv_end
322 
323 end module mom_cvmix_conv
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:80
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_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_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
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_debugging
Provides checksumming functions for debugging.
Definition: MOM_debugging.F90:7
mom_cvmix_conv::cvmix_conv_cs
Control structure including parameters for CVMix convection.
Definition: MOM_CVMix_conv.F90:27
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:26
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:240
mom_cvmix_conv
Interface to CVMix convection scheme.
Definition: MOM_CVMix_conv.F90:2
mom_eos::calculate_density
Calculates density of sea water from T, S and P.
Definition: MOM_EOS.F90:68