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
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  ! Diagnostics arrays
44  real, allocatable, dimension(:,:,:) :: n2 !< Squared Brunt-Vaisala frequency [s-2]
45  real, allocatable, dimension(:,:,:) :: kd_conv !< Diffusivity added by convection [Z2 T-1 ~> m2 s-1]
46  real, allocatable, dimension(:,:,:) :: kv_conv !< Viscosity added by convection [Z2 T-1 ~> m2 s-1]
47 
48 end type cvmix_conv_cs
49 
50 character(len=40) :: mdl = "MOM_CVMix_conv" !< This module's name.
51 
52 contains
53 
54 !> Initialized the CVMix convection mixing routine.
55 logical function cvmix_conv_init(Time, G, GV, US, param_file, diag, CS)
56 
57  type(time_type), intent(in) :: time !< The current time.
58  type(ocean_grid_type), intent(in) :: g !< Grid structure.
59  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure.
60  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
61  type(param_file_type), intent(in) :: param_file !< Run-time parameter file handle
62  type(diag_ctrl), target, intent(inout) :: diag !< Diagnostics control structure.
63  type(cvmix_conv_cs), pointer :: cs !< This module's control structure.
64  ! Local variables
65  real :: prandtl_conv !< Turbulent Prandtl number used in convective instabilities.
66  logical :: useepbl !< If True, use the ePBL boundary layer scheme.
67 
68 ! This include declares and sets the variable "version".
69 #include "version_variable.h"
70 
71  if (associated(cs)) then
72  call mom_error(warning, "CVMix_conv_init called with an associated "// &
73  "control structure.")
74  return
75  endif
76  allocate(cs)
77 
78  ! Read parameters
79  call log_version(param_file, mdl, version, &
80  "Parameterization of enhanced mixing due to convection via CVMix")
81  call get_param(param_file, mdl, "USE_CVMix_CONVECTION", cvmix_conv_init, &
82  "If true, turns on the enhanced mixing due to convection "//&
83  "via CVMix. This scheme increases diapycnal diffs./viscs. "//&
84  "at statically unstable interfaces. Relevant parameters are "//&
85  "contained in the CVMix_CONVECTION% parameter block.", &
86  default=.false.)
87 
88  if (.not. cvmix_conv_init) return
89 
90  call get_param(param_file, mdl, "ENERGETICS_SFC_PBL", useepbl, default=.false., &
91  do_not_log=.true.)
92 
93  ! Warn user if EPBL is being used, since in this case mixing due to convection will
94  ! be aplied in the boundary layer
95  if (useepbl) then
96  call mom_error(warning, 'MOM_CVMix_conv_init: '// &
97  'CVMix convection may not be properly applied when ENERGETICS_SFC_PBL = True'//&
98  'as convective mixing might occur in the boundary layer.')
99  endif
100 
101  call get_param(param_file, mdl, 'DEBUG', cs%debug, default=.false., do_not_log=.true.)
102 
103  call get_param(param_file, mdl, 'MIN_THICKNESS', cs%min_thickness, default=0.001, do_not_log=.true.)
104 
105  call openparameterblock(param_file,'CVMix_CONVECTION')
106 
107  call get_param(param_file, mdl, "PRANDTL_CONV", prandtl_conv, &
108  "The turbulent Prandtl number applied to convective "//&
109  "instabilities (i.e., used to convert KD_CONV into KV_CONV)", &
110  units="nondim", default=1.0)
111 
112  call get_param(param_file, mdl, 'KD_CONV', cs%kd_conv_const, &
113  "Diffusivity used in convective regime. Corresponding viscosity "//&
114  "(KV_CONV) will be set to KD_CONV * PRANDTL_TURB.", &
115  units='m2/s', default=1.00)
116 
117  call get_param(param_file, mdl, 'BV_SQR_CONV', cs%bv_sqr_conv, &
118  "Threshold for squared buoyancy frequency needed to trigger "//&
119  "Brunt-Vaisala parameterization.", &
120  units='1/s^2', default=0.0)
121 
122  call closeparameterblock(param_file)
123 
124  ! set kv_conv_const based on kd_conv_const and prandtl_conv
125  cs%kv_conv_const = cs%kd_conv_const * prandtl_conv
126 
127  ! allocate arrays and set them to zero
128  allocate(cs%N2(szi_(g), szj_(g), szk_(g)+1)); cs%N2(:,:,:) = 0.
129  allocate(cs%kd_conv(szi_(g), szj_(g), szk_(g)+1)); cs%kd_conv(:,:,:) = 0.
130  allocate(cs%kv_conv(szi_(g), szj_(g), szk_(g)+1)); cs%kv_conv(:,:,:) = 0.
131 
132  ! Register diagnostics
133  cs%diag => diag
134  cs%id_N2 = register_diag_field('ocean_model', 'N2_conv', diag%axesTi, time, &
135  'Square of Brunt-Vaisala frequency used by MOM_CVMix_conv module', '1/s2')
136  cs%id_kd_conv = register_diag_field('ocean_model', 'kd_conv', diag%axesTi, time, &
137  'Additional diffusivity added by MOM_CVMix_conv module', 'm2/s', conversion=us%Z2_T_to_m2_s)
138  cs%id_kv_conv = register_diag_field('ocean_model', 'kv_conv', diag%axesTi, time, &
139  'Additional viscosity added by MOM_CVMix_conv module', 'm2/s', conversion=us%Z2_T_to_m2_s)
140 
141  call cvmix_init_conv(convect_diff=cs%kd_conv_const, &
142  convect_visc=cs%kv_conv_const, &
143  lbruntvaisala=.true., &
144  bvsqr_convect=cs%bv_sqr_conv)
145 
146 end function cvmix_conv_init
147 
148 !> Subroutine for calculating enhanced diffusivity/viscosity
149 !! due to convection via CVMix
150 subroutine calculate_cvmix_conv(h, tv, G, GV, US, CS, hbl)
151 
152  type(ocean_grid_type), intent(in) :: g !< Grid structure.
153  type(verticalgrid_type), intent(in) :: gv !< Vertical grid structure.
154  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
155  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2].
156  type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamics structure.
157  type(cvmix_conv_cs), pointer :: cs !< The control structure returned
158  !! by a previous call to CVMix_conv_init.
159  real, dimension(:,:), optional, pointer :: hbl!< Depth of ocean boundary layer [m]
160  ! local variables
161  real, dimension(SZK_(G)) :: rho_lwr !< Adiabatic Water Density, this is a dummy
162  !! variable since here convection is always
163  !! computed based on Brunt Vaisala.
164  real, dimension(SZK_(G)) :: rho_1d !< water density in a column, this is also
165  !! a dummy variable, same reason as above.
166  real, dimension(SZK_(G)+1) :: kv_col !< Viscosities at interfaces in the column [m2 s-1]
167  real, dimension(SZK_(G)+1) :: kd_col !< Diffusivities at interfaces in the column [m2 s-1]
168  real, dimension(SZK_(G)+1) :: ifaceheight !< Height of interfaces [m]
169  real, dimension(SZK_(G)) :: cellheight !< Height of cell centers [m]
170  integer :: kobl !< level of OBL extent
171  real :: g_o_rho0 ! Gravitational acceleration divided by density in MKS units [m4 s-2]
172  real :: pref, rhok, rhokm1, dz, dh, hcorr
173  integer :: i, j, k
174 
175  g_o_rho0 = gv%mks_g_Earth / gv%Rho0
176 
177  ! initialize dummy variables
178  rho_lwr(:) = 0.0; rho_1d(:) = 0.0
179 
180  if (.not. associated(hbl)) then
181  allocate(hbl(szi_(g), szj_(g)))
182  hbl(:,:) = 0.0
183  endif
184 
185  do j = g%jsc, g%jec
186  do i = g%isc, g%iec
187 
188  ! set N2 to zero at the top- and bottom-most interfaces
189  cs%N2(i,j,1) = 0.
190  cs%N2(i,j,g%ke+1) = 0.
191 
192  ! skip calling at land points
193  !if (G%mask2dT(i,j) == 0.) cycle
194 
195  pref = 0.
196  ! Compute Brunt-Vaisala frequency (static stability) on interfaces
197  do k=2,g%ke
198 
199  ! pRef is pressure at interface between k and km1.
200  pref = pref + gv%H_to_Pa * h(i,j,k)
201  call calculate_density(tv%t(i,j,k), tv%s(i,j,k), pref, rhok, tv%eqn_of_state)
202  call calculate_density(tv%t(i,j,k-1), tv%s(i,j,k-1), pref, rhokm1, tv%eqn_of_state)
203 
204  dz = ((0.5*(h(i,j,k-1) + h(i,j,k))+gv%H_subroundoff)*gv%H_to_m)
205  cs%N2(i,j,k) = g_o_rho0 * (rhok - rhokm1) / dz ! Can be negative
206 
207  enddo
208 
209  ifaceheight(1) = 0.0 ! BBL is all relative to the surface
210  hcorr = 0.0
211  ! compute heights at cell center and interfaces
212  do k=1,g%ke
213  dh = h(i,j,k) * gv%H_to_m ! Nominal thickness to use for increment
214  dh = dh + hcorr ! Take away the accumulated error (could temporarily make dh<0)
215  hcorr = min( dh - cs%min_thickness, 0. ) ! If inflating then hcorr<0
216  dh = max( dh, cs%min_thickness ) ! Limit increment dh>=min_thickness
217  cellheight(k) = ifaceheight(k) - 0.5 * dh
218  ifaceheight(k+1) = ifaceheight(k) - dh
219  enddo
220 
221  ! gets index of the level and interface above hbl
222  kobl = cvmix_kpp_compute_kobl_depth(ifaceheight, cellheight,hbl(i,j))
223 
224  kv_col(:) = 0.0 ; kd_col(:) = 0.0
225  call cvmix_coeffs_conv(mdiff_out=kv_col(:), &
226  tdiff_out=kd_col(:), &
227  nsqr=cs%N2(i,j,:), &
228  dens=rho_1d(:), &
229  dens_lwr=rho_lwr(:), &
230  nlev=g%ke, &
231  max_nlev=g%ke, &
232  obl_ind=kobl)
233 
234  do k=1,g%ke+1
235  cs%kv_conv(i,j,k) = us%m2_s_to_Z2_T * kv_col(k)
236  cs%Kd_conv(i,j,k) = us%m2_s_to_Z2_T * kd_col(k)
237  enddo
238  ! Do not apply mixing due to convection within the boundary layer
239  do k=1,kobl
240  cs%kv_conv(i,j,k) = 0.0
241  cs%kd_conv(i,j,k) = 0.0
242  enddo
243 
244  enddo
245  enddo
246 
247  if (cs%debug) then
248  call hchksum(cs%N2, "MOM_CVMix_conv: N2",g%HI,haloshift=0)
249  call hchksum(cs%kd_conv, "MOM_CVMix_conv: kd_conv",g%HI,haloshift=0,scale=us%Z2_T_to_m2_s)
250  call hchksum(cs%kv_conv, "MOM_CVMix_conv: kv_conv",g%HI,haloshift=0,scale=us%m2_s_to_Z2_T)
251  endif
252 
253  ! send diagnostics to post_data
254  if (cs%id_N2 > 0) call post_data(cs%id_N2, cs%N2, cs%diag)
255  if (cs%id_kd_conv > 0) call post_data(cs%id_kd_conv, cs%kd_conv, cs%diag)
256  if (cs%id_kv_conv > 0) call post_data(cs%id_kv_conv, cs%kv_conv, cs%diag)
257 
258 end subroutine calculate_cvmix_conv
259 
260 !> Reads the parameter "USE_CVMix_CONVECTION" and returns state.
261 !! This function allows other modules to know whether this parameterization will
262 !! be used without needing to duplicate the log entry.
263 logical function cvmix_conv_is_used(param_file)
264  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
265  call get_param(param_file, mdl, "USE_CVMix_CONVECTION", cvmix_conv_is_used, &
266  default=.false., do_not_log = .true.)
267 
268 end function cvmix_conv_is_used
269 
270 !> Clear pointers and dealocate memory
271 subroutine cvmix_conv_end(CS)
272  type(cvmix_conv_cs), pointer :: cs !< Control structure for this module that
273  !! will be deallocated in this subroutine
274 
275  if (.not. associated(cs)) return
276 
277  deallocate(cs%N2)
278  deallocate(cs%kd_conv)
279  deallocate(cs%kv_conv)
280  deallocate(cs)
281 
282 end subroutine cvmix_conv_end
283 
284 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:82
mom_eos
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
mom_file_parser::param_file_type
A structure that can be parsed to read and document run-time parameters.
Definition: MOM_file_parser.F90:54
mom_file_parser::get_param
An overloaded interface to read and log the values of various types of parameters.
Definition: MOM_file_parser.F90:102
mom_unit_scaling::unit_scale_type
Describes various unit conversion factors.
Definition: MOM_unit_scaling.F90:14
mom_diag_mediator::post_data
Make a diagnostic available for averaging or output.
Definition: MOM_diag_mediator.F90:70
mom_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:25
mom_diag_mediator::diag_ctrl
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Definition: MOM_diag_mediator.F90:239
mom_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:60