@@ -18,6 +18,8 @@ module MOM_lateral_mixing_coeffs
18
18
use MOM_verticalGrid, only : verticalGrid_type
19
19
use MOM_wave_speed, only : wave_speed, wave_speed_CS, wave_speed_init
20
20
use MOM_open_boundary, only : ocean_OBC_type
21
+ use MOM_MEKE_types, only : MEKE_type
22
+
21
23
22
24
implicit none ; private
23
25
@@ -112,9 +114,12 @@ module MOM_lateral_mixing_coeffs
112
114
113
115
real , allocatable :: slope_x(:,:,:) ! < Zonal isopycnal slope [Z L-1 ~> nondim]
114
116
real , allocatable :: slope_y(:,:,:) ! < Meridional isopycnal slope [Z L-1 ~> nondim]
115
- real , allocatable :: ebt_struct(:,:,:) ! < Vertical structure function to scale diffusivities with [nondim]
117
+ real , allocatable :: ebt_struct(:,:,:) ! < EBT vertical structure to scale diffusivities with [nondim]
118
+ real , allocatable :: sqg_struct(:,:,:) ! < SQG vertical structure to scale diffusivities with [nondim]
116
119
real , allocatable :: BS_struct(:,:,:) ! < Vertical structure function used in backscatter [nondim]
117
120
real :: BS_EBT_power ! < Power to raise EBT vertical structure to. Default 0.0.
121
+ real :: sqg_expo ! < Exponent for SQG vertical structure [nondim]. Default 0.0
122
+ logical :: BS_use_sqg ! < If true, use sqg_stuct for backscatter vertical structure.
118
123
119
124
120
125
real ALLOCABLE_, dimension (NIMEMB_PTR_,NJMEM_) :: &
@@ -163,6 +168,7 @@ module MOM_lateral_mixing_coeffs
163
168
integer :: id_N2_u=- 1 , id_N2_v=- 1 , id_S2_u=- 1 , id_S2_v=- 1
164
169
integer :: id_dzu=- 1 , id_dzv=- 1 , id_dzSxN=- 1 , id_dzSyN=- 1
165
170
integer :: id_Rd_dx=- 1 , id_KH_u_QG = - 1 , id_KH_v_QG = - 1
171
+ integer :: id_sqg_struct=- 1 , id_BS_struct=- 1
166
172
type (diag_ctrl), pointer :: diag ! < A structure that is used to regulate the
167
173
! ! timing of diagnostic output.
168
174
! >@}
@@ -173,7 +179,7 @@ module MOM_lateral_mixing_coeffs
173
179
end type VarMix_CS
174
180
175
181
public VarMix_init, VarMix_end, calc_slope_functions, calc_resoln_function
176
- public calc_QG_slopes, calc_QG_Leith_viscosity, calc_depth_function
182
+ public calc_QG_slopes, calc_QG_Leith_viscosity, calc_depth_function, calc_sqg_struct
177
183
178
184
contains
179
185
@@ -214,13 +220,14 @@ subroutine calc_depth_function(G, CS)
214
220
end subroutine calc_depth_function
215
221
216
222
! > Calculates and stores the non-dimensional resolution functions
217
- subroutine calc_resoln_function (h , tv , G , GV , US , CS )
223
+ subroutine calc_resoln_function (h , tv , G , GV , US , CS , MEKE )
218
224
type (ocean_grid_type), intent (inout ) :: G ! < Ocean grid structure
219
225
type (verticalGrid_type), intent (in ) :: GV ! < Vertical grid structure
220
226
real , dimension (SZI_(G),SZJ_(G),SZK_(GV)), intent (in ) :: h ! < Layer thickness [H ~> m or kg m-2]
221
227
type (thermo_var_ptrs), intent (in ) :: tv ! < Thermodynamic variables
222
228
type (unit_scale_type), intent (in ) :: US ! < A dimensional unit scaling type
223
229
type (VarMix_CS), intent (inout ) :: CS ! < Variable mixing control structure
230
+ type (MEKE_type), intent (in ) :: MEKE ! < MEKE struct
224
231
225
232
! Local variables
226
233
! Depending on the power-function being used, dimensional rescaling may be limited, so some
@@ -230,6 +237,7 @@ subroutine calc_resoln_function(h, tv, G, GV, US, CS)
230
237
real :: cg1_v ! The gravity wave speed interpolated to v points [L T-1 ~> m s-1] or [m s-1].
231
238
real :: dx_term ! A term in the denominator [L2 T-2 ~> m2 s-2] or [m2 s-2]
232
239
integer :: power_2
240
+ real :: dt ! < Time increment [T ~> s]
233
241
integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
234
242
integer :: i, j, k
235
243
is = G% isc ; ie = G% iec ; js = G% jsc ; je = G% jec ; nz = GV% ke
@@ -261,10 +269,19 @@ subroutine calc_resoln_function(h, tv, G, GV, US, CS)
261
269
call create_group_pass(CS% pass_cg1, CS% cg1, G% Domain)
262
270
call do_group_pass(CS% pass_cg1, G% Domain)
263
271
endif
272
+ if (CS% sqg_expo> 0.0 ) then
273
+ call calc_sqg_struct(h, tv, G, GV, US, CS, dt, MEKE)
274
+ call pass_var(CS% sqg_struct, G% Domain)
275
+ endif
276
+
264
277
if (CS% BS_EBT_power> 0 .) then
265
278
do k= 1 ,nz ; do j= G% jsd,G% jed ; do i= G% isd,G% ied
266
279
CS% BS_struct(i,j,k) = CS% ebt_struct(i,j,k)** CS% BS_EBT_power
267
280
enddo ; enddo ; enddo
281
+ elseif (CS% BS_use_sqg) then
282
+ do k= 1 ,nz ; do j= G% jsd,G% jed ; do i= G% isd,G% ied
283
+ CS% BS_struct(i,j,k) = CS% sqg_struct(i,j,k)
284
+ enddo ; enddo ; enddo
268
285
endif
269
286
270
287
! Calculate and store the ratio between deformation radius and grid-spacing
@@ -460,6 +477,7 @@ subroutine calc_resoln_function(h, tv, G, GV, US, CS)
460
477
461
478
if (query_averaging_enabled(CS% diag)) then
462
479
if (CS% id_Res_fn > 0 ) call post_data(CS% id_Res_fn, CS% Res_fn_h, CS% diag)
480
+ if (CS% id_BS_struct > 0 ) call post_data(CS% id_BS_struct, CS% BS_struct, CS% diag)
463
481
endif
464
482
465
483
if (CS% debug) then
@@ -470,6 +488,77 @@ subroutine calc_resoln_function(h, tv, G, GV, US, CS)
470
488
471
489
end subroutine calc_resoln_function
472
490
491
+ ! > Calculates and stores functions of SQG mode
492
+ subroutine calc_sqg_struct (h , tv , G , GV , US , CS , dt , MEKE )
493
+ type (ocean_grid_type), intent (inout ) :: G ! < Ocean grid structure
494
+ type (verticalGrid_type), intent (in ) :: GV ! < Vertical grid structure
495
+ type (unit_scale_type), intent (in ) :: US ! < A dimensional unit scaling type
496
+ real , dimension (SZI_(G),SZJ_(G),SZK_(GV)), intent (in ) :: h ! < Layer thickness [H ~> m or kg m-2]
497
+ type (thermo_var_ptrs), intent (in ) :: tv ! <Thermodynamic variables
498
+ real , intent (in ) :: dt ! < Time increment [T ~> s]
499
+ type (VarMix_CS), intent (inout ) :: CS ! < Variable mixing control struct
500
+ type (MEKE_type), intent (in ) :: MEKE ! < MEKE struct
501
+ ! type(ocean_OBC_type), pointer :: OBC !< Open
502
+ ! boundaries control structure.
503
+
504
+ ! Local variables
505
+ real , dimension (SZI_(G), SZJ_(G),SZK_(GV)+ 1 ) :: &
506
+ e ! The interface heights relative to mean sea level [Z ~> m].
507
+ real , dimension (SZIB_(G), SZJ_(G),SZK_(GV)+ 1 ) :: N2_u ! Square of Brunt-Vaisala freq at u-points [L2 Z-2 T-2 ~> s-2]
508
+ real , dimension (SZI_(G), SZJB_(G),SZK_(GV)+ 1 ) :: N2_v ! Square of Brunt-Vaisala freq at v-points [L2 Z-2 T-2 ~> s-2]
509
+ real , dimension (SZIB_(G), SZJ_(G),SZK_(GV)+ 1 ) :: dzu ! Z-thickness at u-points [Z ~> m]
510
+ real , dimension (SZI_(G), SZJB_(G),SZK_(GV)+ 1 ) :: dzv ! Z-thickness at v-points [Z ~> m]
511
+ real , dimension (SZIB_(G), SZJ_(G),SZK_(GV)+ 1 ) :: dzSxN ! |Sx| N times dz at u-points [Z T-1 ~> m s-1]
512
+ real , dimension (SZI_(G), SZJB_(G),SZK_(GV)+ 1 ) :: dzSyN ! |Sy| N times dz at v-points [Z T-1 ~> m s-1]
513
+ real , dimension (SZI_(G), SZJ_(G)) :: f ! Absolute value of the Coriolis parameter at h point [T-1 ~> s-1]
514
+ real :: N2 ! Positive buoyancy frequency square or zero [L2 Z-2 T-2 ~> s-2]
515
+ real :: dzc ! Spacing between two adjacent layers in stretched vertical coordinate [m]
516
+ ! real, dimension(SZK_(GV)) :: zs ! Stretched vertical coordinate [m]
517
+ real , dimension (SZI_(G), SZJ_(G)) :: Le ! Eddy length scale [m]
518
+ integer :: i, j, k, is, ie, js, je, nz
519
+
520
+ is = G% isc ; ie = G% iec ; js = G% jsc ; je = G% jec ; nz = GV% ke
521
+
522
+ if (.not. CS% initialized) call MOM_error(FATAL, " MOM_lateral_mixing_coeffs.F90, calc_slope_functions: " // &
523
+ " Module must be initialized before it is used." )
524
+
525
+ call find_eta(h, tv, G, GV, US, e, halo_size= 2 )
526
+ call calc_isoneutral_slopes(G, GV, US, h, e, tv, dt* CS% kappa_smooth, CS% use_stanley_iso, &
527
+ CS% slope_x, CS% slope_y, N2_u= N2_u, N2_v= N2_v,dzu= dzu, dzv= dzv, &
528
+ dzSxN= dzSxN, dzSyN= dzSyN, halo= 1 )
529
+
530
+ do j= js,je ; do i= is,ie
531
+ CS% sqg_struct(i,j,1 ) = 1.0
532
+ enddo ; enddo
533
+ if (allocated (MEKE% Le)) then
534
+ do j= js,je ; do i= is,ie
535
+ Le(i,j) = MEKE% Le(i,j)
536
+ f(i,j) = max (0.25 * abs (G% CoriolisBu(I,J) + G% CoriolisBu(I-1 ,J-1 ) + &
537
+ G% CoriolisBu(I-1 ,J) + G% CoriolisBu(I,J-1 )), 1.0e-8 )
538
+ enddo ; enddo
539
+ else
540
+ do j= js,je ; do i= is,ie
541
+ Le(i,j) = sqrt (G% areaT(i,j))
542
+ f(i,j) = max (0.25 * abs (G% CoriolisBu(I,J) + G% CoriolisBu(I-1 ,J-1 ) + &
543
+ G% CoriolisBu(I-1 ,J) + G% CoriolisBu(I,J-1 )), 1.0e-8 )
544
+ enddo ; enddo
545
+ endif
546
+ do k= 2 ,nz ; do j= js,je ; do i= is,ie
547
+ N2 = max (0.25 * (N2_u(I-1 ,j,k) + N2_u(I,j,k) + N2_v(i,J-1 ,k) + N2_v(i,J,k)),0.0 )
548
+ dzc = 0.25 * (dzu(I-1 ,j,k) + dzu(I,j,k) + dzv(i,J-1 ,k) + dzv(i,J,k))* N2** 0.5 / f(i,j)
549
+ ! dzs = -N2**0.5/f(i,j)*dzc
550
+ CS% sqg_struct(i,j,k) = CS% sqg_struct(i,j,k-1 )* exp (- CS% sqg_expo* dzc/ Le(i,j))
551
+ enddo ; enddo ; enddo
552
+
553
+
554
+ if (query_averaging_enabled(CS% diag)) then
555
+ if (CS% id_sqg_struct > 0 ) call post_data(CS% id_sqg_struct, CS% sqg_struct, CS% diag)
556
+ if (CS% id_N2_u > 0 ) call post_data(CS% id_N2_u, N2_u, CS% diag)
557
+ if (CS% id_N2_v > 0 ) call post_data(CS% id_N2_v, N2_v, CS% diag)
558
+ endif
559
+
560
+ end subroutine calc_sqg_struct
561
+
473
562
! > Calculates and stores functions of isopycnal slopes, e.g. Sx, Sy, S*N, mostly used in the Visbeck et al.
474
563
! ! style scaling of diffusivity
475
564
subroutine calc_slope_functions (h , tv , dt , G , GV , US , CS , OBC )
@@ -1260,6 +1349,15 @@ subroutine VarMix_init(Time, G, GV, US, param_file, diag, CS)
1260
1349
call get_param(param_file, mdl, " BACKSCAT_EBT_POWER" , CS% BS_EBT_power, &
1261
1350
" Power to raise EBT vertical structure to when backscatter " // &
1262
1351
" has vertical structure." , units= " nondim" , default= 0.0 )
1352
+ call get_param(param_file, mdl, " BS_USE_SQG" , CS% BS_use_sqg, &
1353
+ " If true, the SQG vertical structure is used for backscatter " // &
1354
+ " on the condition that BS_EBT_power=0" , &
1355
+ default= .false. )
1356
+ if (CS% BS_EBT_power> 0 .) CS% BS_use_sqg = .false.
1357
+ call get_param(param_file, mdl, " SQG_EXPO" , CS% sqg_expo, &
1358
+ " Nondimensional exponent coeffecient of the SQG mode " // &
1359
+ " that is used for the vertical struture of diffusivities." , units= " nondim" , default= 0.0 )
1360
+ if (CS% sqg_expo== 0 .) CS% BS_use_sqg = .false.
1263
1361
call get_param(param_file, mdl, " KHTH_USE_EBT_STRUCT" , CS% khth_use_ebt_struct, &
1264
1362
" If true, uses the equivalent barotropic structure " // &
1265
1363
" as the vertical structure of thickness diffusivity." ,&
@@ -1320,6 +1418,10 @@ subroutine VarMix_init(Time, G, GV, US, param_file, diag, CS)
1320
1418
units= " m" , default=- 1.0 , scale= GV% m_to_H)
1321
1419
allocate (CS% ebt_struct(isd:ied,jsd:jed,GV% ke), source= 0.0 )
1322
1420
endif
1421
+ if (CS% sqg_expo> 0.0 ) then
1422
+ allocate (CS% sqg_struct(isd:ied,jsd:jed,GV% ke), source= 0.0 )
1423
+ endif
1424
+
1323
1425
allocate (CS% BS_struct(isd:ied,jsd:jed,GV% ke), source= 0.0 )
1324
1426
CS% BS_struct(:,:,:) = 1.0
1325
1427
@@ -1335,7 +1437,7 @@ subroutine VarMix_init(Time, G, GV, US, param_file, diag, CS)
1335
1437
endif
1336
1438
endif
1337
1439
1338
- if (CS% use_stored_slopes) then
1440
+ if (CS% use_stored_slopes .or. CS % sqg_expo > 0.0 ) then
1339
1441
! CS%calculate_Eady_growth_rate=.true.
1340
1442
in_use = .true.
1341
1443
allocate (CS% slope_x(IsdB:IedB,jsd:jed,GV% ke+1 ), source= 0.0 )
@@ -1418,7 +1520,15 @@ subroutine VarMix_init(Time, G, GV, US, param_file, diag, CS)
1418
1520
' m2' , conversion= US% L_to_m** 2 )
1419
1521
endif
1420
1522
1421
- if (CS% calculate_Eady_growth_rate .and. CS% use_stored_slopes) then
1523
+ if (CS% sqg_expo> 0.0 ) then
1524
+ CS% id_sqg_struct = register_diag_field(' ocean_model' , ' sqg_struct' , diag% axesTl, Time, &
1525
+ ' Vertical structure of SQG mode' , ' nondim' )
1526
+ endif
1527
+
1528
+ CS% id_BS_struct = register_diag_field(' ocean_model' , ' BS_struct' , diag% axesTl, Time, &
1529
+ ' Vertical structure of backscatter' , ' nondim' )
1530
+
1531
+ if ((CS% calculate_Eady_growth_rate .and. CS% use_stored_slopes) .or. (CS% sqg_expo> 0.0 )) then
1422
1532
CS% id_N2_u = register_diag_field(' ocean_model' , ' N2_u' , diag% axesCui, Time, &
1423
1533
' Square of Brunt-Vaisala frequency, N^2, at u-points, as used in Visbeck et al.' , &
1424
1534
' s-2' , conversion= (US% L_to_Z* US% s_to_T)** 2 )
@@ -1672,9 +1782,10 @@ subroutine VarMix_end(CS)
1672
1782
1673
1783
if (CS% Resoln_use_ebt .or. CS% khth_use_ebt_struct .or. CS% kdgl90_use_ebt_struct .or. CS% BS_EBT_power> 0 .) &
1674
1784
deallocate (CS% ebt_struct)
1785
+ if (CS% sqg_expo> 0.0 ) deallocate (CS% sqg_struct)
1675
1786
if (allocated (CS% BS_struct)) deallocate (CS% BS_struct)
1676
1787
1677
- if (CS% use_stored_slopes) then
1788
+ if (CS% use_stored_slopes .or. CS % sqg_expo > 0.0 ) then
1678
1789
deallocate (CS% slope_x)
1679
1790
deallocate (CS% slope_y)
1680
1791
endif
0 commit comments