9 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, clock_routine
24 implicit none ;
private
26 #include <MOM_memory.h>
28 public step_forward_meke, meke_init, meke_alloc_register_restart, meke_end
41 real :: meke_min_gamma
44 logical :: jansen15_drag
45 logical :: meke_geometric
49 logical :: rd_as_max_scale
51 logical :: use_old_lscale
52 logical :: use_min_lscale
62 real :: viscosity_coeff_ku
65 real :: viscosity_coeff_au
74 real :: meke_advection_factor
75 real :: meke_topographic_beta
77 logical :: kh_flux_enabled
83 integer :: id_meke = -1, id_ue = -1, id_kh = -1, id_src = -1
84 integer :: id_ub = -1, id_ut = -1
85 integer :: id_gm_src = -1, id_mom_src = -1, id_gme_snk = -1, id_decay = -1
86 integer :: id_khmeke_u = -1, id_khmeke_v = -1, id_ku = -1, id_au = -1
87 integer :: id_le = -1, id_gamma_b = -1, id_gamma_t = -1
88 integer :: id_lrhines = -1, id_leady = -1
92 integer :: id_clock_pass
93 type(group_pass_type) :: pass_meke
94 type(group_pass_type) :: pass_kh
101 subroutine step_forward_meke(MEKE, h, SN_u, SN_v, visc, dt, G, GV, US, CS, hu, hv)
106 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
107 real,
dimension(SZIB_(G),SZJ_(G)),
intent(inout) :: sn_u
108 real,
dimension(SZI_(G),SZJB_(G)),
intent(inout) :: sn_v
110 real,
intent(in) :: dt
112 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: hu
113 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: hv
116 real,
dimension(SZI_(G),SZJ_(G)) :: &
132 real,
dimension(SZIB_(G),SZJ_(G)) :: &
138 real,
dimension(SZI_(G),SZJB_(G)) :: &
144 real :: kh_here, inv_kh_max, k4_here
152 logical :: use_drag_rate
153 integer :: i, j, k, is, ie, js, je, isq, ieq, jsq, jeq, nz
155 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
156 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
158 if (.not.
associated(cs))
call mom_error(fatal, &
159 "MOM_MEKE: Module must be initialized before it is used.")
160 if (.not.
associated(meke))
call mom_error(fatal, &
161 "MOM_MEKE: MEKE must be initialized before it is used.")
163 rho0 = gv%H_to_kg_m2 * gv%m_to_H
164 mass_neglect = gv%H_to_kg_m2 * gv%H_subroundoff
165 sdt = dt*cs%MEKE_dtScale
166 if (cs%MEKE_damping + cs%MEKE_Cd_scale > 0.0 .or. cs%MEKE_Cb>0. &
167 .or. cs%visc_drag)
then
168 use_drag_rate = .true.
170 use_drag_rate = .false.
174 if (
associated(meke%MEKE))
then
177 if (
associated(meke%mom_src))
call hchksum(meke%mom_src,
'MEKE mom_src',g%HI)
178 if (
associated(meke%GME_snk))
call hchksum(meke%GME_snk,
'MEKE GME_snk',g%HI)
179 if (
associated(meke%GM_src))
call hchksum(meke%GM_src,
'MEKE GM_src',g%HI)
180 if (
associated(meke%MEKE))
call hchksum(meke%MEKE,
'MEKE MEKE',g%HI)
181 call uvchksum(
"MEKE SN_[uv]", sn_u, sn_v, g%HI)
182 call uvchksum(
"MEKE h[uv]", hu, hv, g%HI, haloshift=1, scale=gv%H_to_m)
186 sdt = dt*cs%MEKE_dtScale
187 rho0 = gv%H_to_kg_m2 * gv%m_to_H
188 mass_neglect = gv%H_to_kg_m2 * gv%H_subroundoff
193 sdt_damp = sdt ;
if (cs%MEKE_KH >= 0.0 .or. cs%MEKE_K4 >= 0.) sdt_damp = 0.5*sdt
196 if (cs%MEKE_advection_factor>0.)
then
197 do j=js,je ;
do i=is-1,ie
201 do j=js,je ;
do i=is-1,ie
202 barohu(i,j) = hu(i,j,k)
205 do j=js-1,je ;
do i=is,ie
209 do j=js-1,je ;
do i=is,ie
210 barohv(i,j) = hv(i,j,k)
215 if (cs%MEKE_Cd_scale == 0.0 .and. .not. cs%visc_drag)
then
217 do j=js,je ;
do i=is,ie
223 if (cs%visc_drag)
then
225 do j=js,je ;
do i=is-1,ie
226 drag_vel_u(i,j) = 0.0
227 if ((g%mask2dCu(i,j) > 0.0) .and. (visc%bbl_thick_u(i,j) > 0.0)) &
228 drag_vel_u(i,j) = us%Z_to_m*us%s_to_T*visc%Kv_bbl_u(i,j) / visc%bbl_thick_u(i,j)
231 do j=js-1,je ;
do i=is,ie
232 drag_vel_v(i,j) = 0.0
233 if ((g%mask2dCv(i,j) > 0.0) .and. (visc%bbl_thick_v(i,j) > 0.0)) &
234 drag_vel_v(i,j) = us%Z_to_m*us%s_to_T*visc%Kv_bbl_v(i,j) / visc%bbl_thick_v(i,j)
238 do j=js,je ;
do i=is,ie
239 drag_rate_visc(i,j) = (0.25*g%IareaT(i,j) * &
240 ((g%areaCu(i-1,j)*drag_vel_u(i-1,j) + &
241 g%areaCu(i,j)*drag_vel_u(i,j)) + &
242 (g%areaCv(i,j-1)*drag_vel_v(i,j-1) + &
243 g%areaCv(i,j)*drag_vel_v(i,j)) ) )
247 do j=js,je ;
do i=is,ie
248 drag_rate_visc(i,j) = 0.
254 do i=is-1,ie+1 ; mass(i,j) = 0.0 ;
enddo
255 do k=1,nz ;
do i=is-1,ie+1
256 mass(i,j) = mass(i,j) + g%mask2dT(i,j) * (gv%H_to_kg_m2 * h(i,j,k))
260 if (mass(i,j) > 0.0) i_mass(i,j) = 1.0 / mass(i,j)
264 if (cs%initialize)
then
265 call meke_equilibrium(cs, meke, g, gv, us, sn_u, sn_v, drag_rate_visc, i_mass)
266 cs%initialize = .false.
270 call meke_lengthscales(cs, meke, g, gv, us, sn_u, sn_v, meke%MEKE, bottomfac2, barotrfac2, lmixscale)
272 call uvchksum(
"MEKE drag_vel_[uv]", drag_vel_u, drag_vel_v, g%HI)
273 call hchksum(mass,
'MEKE mass',g%HI,haloshift=1)
274 call hchksum(drag_rate_visc,
'MEKE drag_rate_visc',g%HI)
275 call hchksum(bottomfac2,
'MEKE bottomFac2',g%HI)
276 call hchksum(barotrfac2,
'MEKE barotrFac2',g%HI)
277 call hchksum(lmixscale,
'MEKE LmixScale',g%HI)
282 do j=js,je ;
do i=is,ie
283 src(i,j) = cs%MEKE_BGsrc
286 if (
associated(meke%mom_src))
then
288 do j=js,je ;
do i=is,ie
289 src(i,j) = src(i,j) - cs%MEKE_FrCoeff*i_mass(i,j)*meke%mom_src(i,j)
293 if (
associated(meke%GME_snk))
then
295 do j=js,je ;
do i=is,ie
296 src(i,j) = src(i,j) - cs%MEKE_GMECoeff*i_mass(i,j)*meke%GME_snk(i,j)
300 if (
associated(meke%GM_src))
then
302 if (cs%GM_src_alt)
then
303 do j=js,je ;
do i=is,ie
304 src(i,j) = src(i,j) - cs%MEKE_GMcoeff*meke%GM_src(i,j) / max(1.0,g%bathyT(i,j))
307 do j=js,je ;
do i=is,ie
308 src(i,j) = src(i,j) - cs%MEKE_GMcoeff*i_mass(i,j)*meke%GM_src(i,j)
315 do j=js,je ;
do i=is,ie
316 meke%MEKE(i,j) = (meke%MEKE(i,j) + sdt*src(i,j) )*g%mask2dT(i,j)
319 if (use_drag_rate)
then
322 if (cs%Jansen15_drag)
then
323 do j=js,je ;
do i=is,ie
324 drag_rate(i,j) = (cdrag2/max(1.0,g%bathyT(i,j))) * sqrt(cs%MEKE_Uscale**2 + drag_rate_visc(i,j)**2 + &
325 2.0*bottomfac2(i,j)*meke%MEKE(i,j)) * 2.0 * bottomfac2(i,j)*meke%MEKE(i,j)
328 do j=js,je ;
do i=is,ie
329 drag_rate(i,j) = (rho0 * i_mass(i,j)) * sqrt( drag_rate_visc(i,j)**2 &
330 + cdrag2 * ( max(0.0, 2.0*bottomfac2(i,j)*meke%MEKE(i,j)) + cs%MEKE_Uscale**2 ) )
337 if (cs%Jansen15_drag)
then
338 do j=js,je ;
do i=is,ie
339 ldamping = cs%MEKE_damping + drag_rate(i,j)
340 meke%MEKE(i,j) = meke%MEKE(i,j) - min(meke%MEKE(i,j),sdt_damp*drag_rate(i,j))
341 meke_decay(i,j) = ldamping*g%mask2dT(i,j)
344 do j=js,je ;
do i=is,ie
345 ldamping = cs%MEKE_damping + drag_rate(i,j) * bottomfac2(i,j)
346 if (meke%MEKE(i,j)<0.) ldamping = 0.
349 meke%MEKE(i,j) = meke%MEKE(i,j) / (1.0 + sdt_damp*ldamping)
350 meke_decay(i,j) = ldamping*g%mask2dT(i,j)
355 if (cs%kh_flux_enabled .or. cs%MEKE_K4 >= 0.0)
then
357 call cpu_clock_begin(cs%id_clock_pass)
358 call do_group_pass(cs%pass_MEKE, g%Domain)
359 call cpu_clock_end(cs%id_clock_pass)
362 if (cs%MEKE_K4 >= 0.0)
then
365 do j=js-1,je+1 ;
do i=is-2,ie+1
366 meke_uflux(i,j) = ((g%dy_Cu(i,j)*g%IdxCu(i,j)) * g%mask2dCu(i,j)) * &
367 (meke%MEKE(i+1,j) - meke%MEKE(i,j))
373 do j=js-2,je+1 ;
do i=is-1,ie+1
374 meke_vflux(i,j) = ((g%dx_Cv(i,j)*g%IdyCv(i,j)) * g%mask2dCv(i,j)) * &
375 (meke%MEKE(i,j+1) - meke%MEKE(i,j))
382 do j=js-1,je+1 ;
do i=is-1,ie+1
383 del2meke(i,j) = g%IareaT(i,j) * &
384 ((meke_uflux(i,j) - meke_uflux(i-1,j)) + (meke_vflux(i,j) - meke_vflux(i,j-1)))
391 do j=js,je ;
do i=is-1,ie
394 inv_kh_max = 64.0*sdt * (((g%dy_Cu(i,j)*g%IdxCu(i,j)) * &
395 max(g%IareaT(i,j),g%IareaT(i+1,j))))**2
396 if (k4_here*inv_kh_max > 0.3) k4_here = 0.3 / inv_kh_max
398 meke_uflux(i,j) = ((k4_here * (g%dy_Cu(i,j)*g%IdxCu(i,j))) * &
399 ((2.0*mass(i,j)*mass(i+1,j)) / ((mass(i,j)+mass(i+1,j)) + mass_neglect)) ) * &
400 (del2meke(i+1,j) - del2meke(i,j))
403 do j=js-1,je ;
do i=is,ie
405 inv_kh_max = 64.0*sdt * (((g%dx_Cv(i,j)*g%IdyCv(i,j)) * &
406 max(g%IareaT(i,j),g%IareaT(i,j+1))))**2
407 if (k4_here*inv_kh_max > 0.3) k4_here = 0.3 / inv_kh_max
409 meke_vflux(i,j) = ((k4_here * (g%dx_Cv(i,j)*g%IdyCv(i,j))) * &
410 ((2.0*mass(i,j)*mass(i,j+1)) / ((mass(i,j)+mass(i,j+1)) + mass_neglect)) ) * &
411 (del2meke(i,j+1) - del2meke(i,j))
415 do j=js,je ;
do i=is,ie
416 del4meke(i,j) = (sdt*(g%IareaT(i,j)*i_mass(i,j))) * &
417 ((meke_uflux(i-1,j) - meke_uflux(i,j)) + &
418 (meke_vflux(i,j-1) - meke_vflux(i,j)))
423 if (cs%kh_flux_enabled)
then
425 kh_here = max(0.,cs%MEKE_Kh)
427 do j=js,je ;
do i=is-1,ie
429 if (
associated(meke%Kh)) &
430 kh_here = max(0.,cs%MEKE_Kh) + cs%KhMEKE_Fac*0.5*(meke%Kh(i,j)+meke%Kh(i+1,j))
431 if (
associated(meke%Kh_diff)) &
432 kh_here = max(0.,cs%MEKE_Kh) + cs%KhMEKE_Fac*0.5*(meke%Kh_diff(i,j)+meke%Kh_diff(i+1,j))
433 inv_kh_max = 2.0*sdt * ((g%dy_Cu(i,j)*g%IdxCu(i,j)) * &
434 max(g%IareaT(i,j),g%IareaT(i+1,j)))
435 if (kh_here*inv_kh_max > 0.25) kh_here = 0.25 / inv_kh_max
438 meke_uflux(i,j) = ((kh_here * (g%dy_Cu(i,j)*g%IdxCu(i,j))) * &
439 ((2.0*mass(i,j)*mass(i+1,j)) / ((mass(i,j)+mass(i+1,j)) + mass_neglect)) ) * &
440 (meke%MEKE(i,j) - meke%MEKE(i+1,j))
443 do j=js-1,je ;
do i=is,ie
444 if (
associated(meke%Kh)) &
445 kh_here = max(0.,cs%MEKE_Kh) + cs%KhMEKE_Fac*0.5*(meke%Kh(i,j)+meke%Kh(i,j+1))
446 if (
associated(meke%Kh_diff)) &
447 kh_here = max(0.,cs%MEKE_Kh) + cs%KhMEKE_Fac*0.5*(meke%Kh_diff(i,j)+meke%Kh_diff(i,j+1))
448 inv_kh_max = 2.0*sdt * ((g%dx_Cv(i,j)*g%IdyCv(i,j)) * &
449 max(g%IareaT(i,j),g%IareaT(i,j+1)))
450 if (kh_here*inv_kh_max > 0.25) kh_here = 0.25 / inv_kh_max
453 meke_vflux(i,j) = ((kh_here * (g%dx_Cv(i,j)*g%IdyCv(i,j))) * &
454 ((2.0*mass(i,j)*mass(i,j+1)) / ((mass(i,j)+mass(i,j+1)) + mass_neglect)) ) * &
455 (meke%MEKE(i,j) - meke%MEKE(i,j+1))
457 if (cs%MEKE_advection_factor>0.)
then
458 advfac = gv%H_to_m * cs%MEKE_advection_factor / dt
460 do j=js,je ;
do i=is-1,ie
461 if (barohu(i,j)>0.)
then
462 meke_uflux(i,j) = meke_uflux(i,j) + barohu(i,j)*meke%MEKE(i,j)*advfac
463 elseif (barohu(i,j)<0.)
then
464 meke_uflux(i,j) = meke_uflux(i,j) + barohu(i,j)*meke%MEKE(i+1,j)*advfac
468 do j=js-1,je ;
do i=is,ie
469 if (barohv(i,j)>0.)
then
470 meke_vflux(i,j) = meke_vflux(i,j) + barohv(i,j)*meke%MEKE(i,j)*advfac
471 elseif (barohv(i,j)<0.)
then
472 meke_vflux(i,j) = meke_vflux(i,j) + barohv(i,j)*meke%MEKE(i,j+1)*advfac
477 do j=js,je ;
do i=is,ie
478 meke%MEKE(i,j) = meke%MEKE(i,j) + (sdt*(g%IareaT(i,j)*i_mass(i,j))) * &
479 ((meke_uflux(i-1,j) - meke_uflux(i,j)) + &
480 (meke_vflux(i,j-1) - meke_vflux(i,j)))
485 if (cs%MEKE_K4 >= 0.0)
then
487 do j=js,je ;
do i=is,ie
488 meke%MEKE(i,j) = meke%MEKE(i,j) + del4meke(i,j)
493 if (cs%MEKE_KH >= 0.0 .or. cs%MEKE_K4 >= 0.0)
then
494 if (sdt>sdt_damp)
then
496 if (use_drag_rate)
then
498 if (cs%Jansen15_drag)
then
499 do j=js,je ;
do i=is,ie
500 ldamping = cs%MEKE_damping + drag_rate(i,j)
501 meke%MEKE(i,j) = meke%MEKE(i,j) -sdt_damp*drag_rate(i,j)
502 meke_decay(i,j) = ldamping*g%mask2dT(i,j)
505 do j=js,je ;
do i=is,ie
506 drag_rate(i,j) = (rho0 * i_mass(i,j)) * sqrt( drag_rate_visc(i,j)**2 &
507 + cdrag2 * ( max(0.0, 2.0*bottomfac2(i,j)*meke%MEKE(i,j)) + cs%MEKE_Uscale**2 ) )
509 do j=js,je ;
do i=is,ie
510 ldamping = cs%MEKE_damping + drag_rate(i,j) * bottomfac2(i,j)
511 if (meke%MEKE(i,j)<0.) ldamping = 0.
514 meke%MEKE(i,j) = meke%MEKE(i,j) / (1.0 + sdt_damp*ldamping)
515 meke_decay(i,j) = ldamping*g%mask2dT(i,j)
528 call cpu_clock_begin(cs%id_clock_pass)
529 call do_group_pass(cs%pass_MEKE, g%Domain)
530 call cpu_clock_end(cs%id_clock_pass)
533 if (cs%MEKE_KhCoeff>0.)
then
534 if (.not.cs%MEKE_GEOMETRIC)
then
535 if (cs%use_old_lscale)
then
536 if (cs%Rd_as_max_scale)
then
538 do j=js,je ;
do i=is,ie
539 meke%Kh(i,j) = (cs%MEKE_KhCoeff &
540 * sqrt(2.*max(0.,barotrfac2(i,j)*meke%MEKE(i,j))*g%areaT(i,j))) &
541 * min(meke%Rd_dx_h(i,j), 1.0)
545 do j=js,je ;
do i=is,ie
546 meke%Kh(i,j) = cs%MEKE_KhCoeff*sqrt(2.*max(0.,barotrfac2(i,j)*meke%MEKE(i,j))*g%areaT(i,j))
551 do j=js,je ;
do i=is,ie
552 meke%Kh(i,j) = (cs%MEKE_KhCoeff*sqrt(2.*max(0.,barotrfac2(i,j)*meke%MEKE(i,j)))*lmixscale(i,j))
559 if (cs%viscosity_coeff_Ku /=0.)
then
560 do j=js,je ;
do i=is,ie
561 meke%Ku(i,j) = us%T_to_s*cs%viscosity_coeff_Ku*sqrt(2.*max(0.,meke%MEKE(i,j)))*lmixscale(i,j)
565 if (cs%viscosity_coeff_Au /=0.)
then
566 do j=js,je ;
do i=is,ie
567 meke%Au(i,j) = us%T_to_s*cs%viscosity_coeff_Au*sqrt(2.*max(0.,meke%MEKE(i,j)))*lmixscale(i,j)**3
571 if (
associated(meke%Kh) .or.
associated(meke%Ku) .or.
associated(meke%Au))
then
572 call cpu_clock_begin(cs%id_clock_pass)
573 call do_group_pass(cs%pass_Kh, g%Domain)
574 call cpu_clock_end(cs%id_clock_pass)
578 if (cs%id_MEKE>0)
call post_data(cs%id_MEKE, meke%MEKE, cs%diag)
579 if (cs%id_Ue>0)
call post_data(cs%id_Ue, sqrt(max(0.,2.0*meke%MEKE)), cs%diag)
580 if (cs%id_Ub>0)
call post_data(cs%id_Ub, sqrt(max(0.,2.0*meke%MEKE*bottomfac2)), cs%diag)
581 if (cs%id_Ut>0)
call post_data(cs%id_Ut, sqrt(max(0.,2.0*meke%MEKE*barotrfac2)), cs%diag)
582 if (cs%id_Kh>0)
call post_data(cs%id_Kh, meke%Kh, cs%diag)
583 if (cs%id_Ku>0)
call post_data(cs%id_Ku, meke%Ku, cs%diag)
584 if (cs%id_Au>0)
call post_data(cs%id_Au, meke%Au, cs%diag)
585 if (cs%id_KhMEKE_u>0)
call post_data(cs%id_KhMEKE_u, kh_u, cs%diag)
586 if (cs%id_KhMEKE_v>0)
call post_data(cs%id_KhMEKE_v, kh_v, cs%diag)
587 if (cs%id_src>0)
call post_data(cs%id_src, src, cs%diag)
588 if (cs%id_decay>0)
call post_data(cs%id_decay, meke_decay, cs%diag)
589 if (cs%id_GM_src>0)
call post_data(cs%id_GM_src, meke%GM_src, cs%diag)
590 if (cs%id_mom_src>0)
call post_data(cs%id_mom_src, meke%mom_src, cs%diag)
591 if (cs%id_GME_snk>0)
call post_data(cs%id_GME_snk, meke%GME_snk, cs%diag)
592 if (cs%id_Le>0)
call post_data(cs%id_Le, lmixscale, cs%diag)
593 if (cs%id_gamma_b>0)
then
594 do j=js,je ;
do i=is,ie
595 bottomfac2(i,j) = sqrt(bottomfac2(i,j))
597 call post_data(cs%id_gamma_b, bottomfac2, cs%diag)
599 if (cs%id_gamma_t>0)
then
600 do j=js,je ;
do i=is,ie
601 barotrfac2(i,j) = sqrt(barotrfac2(i,j))
603 call post_data(cs%id_gamma_t, barotrfac2, cs%diag)
610 end subroutine step_forward_meke
615 subroutine meke_equilibrium(CS, MEKE, G, GV, US, SN_u, SN_v, drag_rate_visc, I_mass)
621 real,
dimension(SZIB_(G),SZJ_(G)),
intent(in) :: SN_u
622 real,
dimension(SZI_(G),SZJB_(G)),
intent(in) :: SN_v
623 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: drag_rate_visc
624 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: I_mass
626 real :: beta, SN, bottomFac2, barotrFac2, LmixScale, Lrhines, Leady
627 real :: I_H, KhCoeff, Kh, Ubg2, cd2, drag_rate, ldamping, src
628 real :: EKE, EKEmin, EKEmax, resid, ResMin, ResMax, EKEerr
630 real :: beta_topo_x, beta_topo_y
631 integer :: i, j, is, ie, js, je, n1, n2
632 real,
parameter :: tolerance = 1.e-12
633 logical :: useSecant, debugIteration
635 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
637 debugiteration = .false.
638 khcoeff = cs%MEKE_KhCoeff
639 ubg2 = cs%MEKE_Uscale**2
643 do j=js,je ;
do i=is,ie
646 sn = min( min(sn_u(i,j) , sn_u(i-1,j)) , min(sn_v(i,j), sn_v(i,j-1)) )
648 fath = 0.25*us%s_to_T*((g%CoriolisBu(i,j) + g%CoriolisBu(i-1,j-1)) + &
649 (g%CoriolisBu(i-1,j) + g%CoriolisBu(i,j-1)))
652 if (cs%MEKE_topographic_beta == 0. .or. g%bathyT(i,j) == 0.)
then
653 beta_topo_x = 0. ; beta_topo_y = 0.
657 beta_topo_x = cs%MEKE_topographic_beta * fath * 0.5 * ( &
658 (g%bathyT(i+1,j)-g%bathyT(i,j)) * g%IdxCu(i,j) &
659 /max(g%bathyT(i+1,j),g%bathyT(i,j), gv%H_subroundoff) &
660 + (g%bathyT(i,j)-g%bathyT(i-1,j)) * g%IdxCu(i-1,j) &
661 /max(g%bathyT(i,j),g%bathyT(i-1,j), gv%H_subroundoff) )
662 beta_topo_y = cs%MEKE_topographic_beta * fath * 0.5 * ( &
663 (g%bathyT(i,j+1)-g%bathyT(i,j)) * g%IdyCv(i,j) &
664 /max(g%bathyT(i,j+1),g%bathyT(i,j), gv%H_subroundoff) + &
665 (g%bathyT(i,j)-g%bathyT(i,j-1)) * g%IdxCu(i,j-1) &
666 /max(g%bathyT(i,j),g%bathyT(i,j-1), gv%H_subroundoff) )
669 beta = sqrt((us%s_to_T * g%dF_dx(i,j) - beta_topo_x)**2 &
670 + (us%s_to_T * g%dF_dy(i,j) - beta_topo_y)**2 )
672 i_h = gv%Rho0 * i_mass(i,j)
674 if (khcoeff*sn*i_h>0.)
then
686 call meke_lengthscales_0d(cs, g%areaT(i,j), beta, g%bathyT(i,j), &
687 meke%Rd_dx_h(i,j), sn, eke, us%Z_to_m, &
688 bottomfac2, barotrfac2, lmixscale, &
691 kh = (khcoeff * sqrt(2.*barotrfac2*eke) * lmixscale)
693 drag_rate = i_h * sqrt( drag_rate_visc(i,j)**2 + cd2 * ( 2.0*bottomfac2*eke + ubg2 ) )
694 ldamping = cs%MEKE_damping + drag_rate * bottomfac2
695 resid = src - ldamping * eke
696 if (debugiteration)
then
697 write(0,*) n1,
'EKE=',eke,
'resid=',resid
698 write(0,*)
'EKEmin=',ekemin,
'ResMin=',resmin
699 write(0,*)
'src=',src,
'ldamping=',ldamping
700 write(0,*)
'gamma-b=',bottomfac2,
'gamma-t=',barotrfac2
701 write(0,*)
'drag_visc=',drag_rate_visc(i,j),
'Ubg2=',ubg2
706 if (resid<resmin) usesecant = .true.
708 if (ekemax > 2.e17)
then
709 if (debugiteration) stop
'Something has gone very wrong'
710 debugiteration = .true.
712 ekemin = 0. ; resmin = 0.
721 n2 = 0 ; ekeerr = ekemax - ekemin
722 do while (ekeerr>tolerance)
725 eke = ekemin + (ekemax - ekemin) * (resmin / (resmin - resmax))
727 eke = 0.5 * (ekemin + ekemax)
729 ekeerr = min( eke-ekemin, ekemax-eke )
731 kh = (khcoeff * sqrt(2.*barotrfac2*eke) * lmixscale)
733 drag_rate = i_h * sqrt( drag_rate_visc(i,j)**2 + cd2 * ( 2.0*bottomfac2*eke + ubg2 ) )
734 ldamping = cs%MEKE_damping + drag_rate * bottomfac2
735 resid = src - ldamping * eke
736 if (usesecant.and.resid>resmin) usesecant = .false.
739 if (resid<resmin) usesecant = .true.
741 elseif (resid<0.)
then
747 if (n2>200) stop
'Failing to converge?'
757 end subroutine meke_equilibrium
763 subroutine meke_lengthscales(CS, MEKE, G, GV, US, SN_u, SN_v, &
764 EKE, bottomFac2, barotrFac2, LmixScale)
770 real,
dimension(SZIB_(G),SZJ_(G)),
intent(in) :: SN_u
771 real,
dimension(SZI_(G),SZJB_(G)),
intent(in) :: SN_v
772 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: EKE
773 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: bottomFac2
774 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: barotrFac2
775 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: LmixScale
777 real,
dimension(SZI_(G),SZJ_(G)) :: Lrhines, Leady
780 real :: beta_topo_x, beta_topo_y
781 integer :: i, j, is, ie, js, je
783 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
786 do j=js,je ;
do i=is,ie
787 if (.not.cs%use_old_lscale)
then
788 if (cs%aEady > 0.)
then
789 sn = 0.25*( (sn_u(i,j) + sn_u(i-1,j)) + (sn_v(i,j) + sn_v(i,j-1)) )
793 fath = 0.25*us%s_to_T* ( ( g%CoriolisBu(i,j) + g%CoriolisBu(i-1,j-1) ) + &
794 ( g%CoriolisBu(i-1,j) + g%CoriolisBu(i,j-1) ) )
799 if (cs%MEKE_topographic_beta == 0. .or. g%bathyT(i,j) == 0.0)
then
800 beta_topo_x = 0. ; beta_topo_y = 0.
804 beta_topo_x = cs%MEKE_topographic_beta * fath * 0.5 * ( &
805 (g%bathyT(i+1,j)-g%bathyT(i,j)) * g%IdxCu(i,j) &
806 /max(g%bathyT(i+1,j),g%bathyT(i,j), gv%H_subroundoff) &
807 + (g%bathyT(i,j)-g%bathyT(i-1,j)) * g%IdxCu(i-1,j) &
808 /max(g%bathyT(i,j),g%bathyT(i-1,j), gv%H_subroundoff) )
809 beta_topo_y = cs%MEKE_topographic_beta * fath * 0.5 * ( &
810 (g%bathyT(i,j+1)-g%bathyT(i,j)) * g%IdyCv(i,j) &
811 /max(g%bathyT(i,j+1),g%bathyT(i,j), gv%H_subroundoff) + &
812 (g%bathyT(i,j)-g%bathyT(i,j-1)) * g%IdxCu(i,j-1) &
813 /max(g%bathyT(i,j),g%bathyT(i,j-1), gv%H_subroundoff) )
816 beta = sqrt((us%s_to_T * g%dF_dx(i,j) - beta_topo_x)**2 &
817 + (us%s_to_T * g%dF_dy(i,j) - beta_topo_y)**2 )
823 call meke_lengthscales_0d(cs, g%areaT(i,j), beta, g%bathyT(i,j), &
824 meke%Rd_dx_h(i,j), sn, meke%MEKE(i,j), us%Z_to_m, &
825 bottomfac2(i,j), barotrfac2(i,j), lmixscale(i,j), &
826 lrhines(i,j), leady(i,j))
828 if (cs%id_Lrhines>0)
call post_data(cs%id_Lrhines, lrhines, cs%diag)
829 if (cs%id_Leady>0)
call post_data(cs%id_Leady, leady, cs%diag)
831 end subroutine meke_lengthscales
836 subroutine meke_lengthscales_0d(CS, area, beta, depth, Rd_dx, SN, EKE, Z_to_L, &
837 bottomFac2, barotrFac2, LmixScale, Lrhines, Leady)
839 real,
intent(in) :: area
840 real,
intent(in) :: beta
841 real,
intent(in) :: depth
842 real,
intent(in) :: Rd_dx
843 real,
intent(in) :: SN
844 real,
intent(in) :: EKE
845 real,
intent(in) :: Z_to_L
847 real,
intent(out) :: bottomFac2
848 real,
intent(out) :: barotrFac2
849 real,
intent(out) :: LmixScale
850 real,
intent(out) :: Lrhines
851 real,
intent(out) :: Leady
853 real :: Lgrid, Ldeform, LdeformLim, Ue, Lfrict
857 ldeform = lgrid * rd_dx
858 lfrict = (z_to_l * depth) / cs%cdrag
861 bottomfac2 = cs%MEKE_CD_SCALE**2
862 if (lfrict*cs%MEKE_Cb>0.) bottomfac2 = bottomfac2 + 1./( 1. + cs%MEKE_Cb*(ldeform/lfrict) )**0.8
863 bottomfac2 = max(bottomfac2, cs%MEKE_min_gamma)
867 if (lfrict*cs%MEKE_Ct>0.) barotrfac2 = 1./( 1. + cs%MEKE_Ct*(ldeform/lfrict) )**0.25
868 barotrfac2 = max(barotrfac2, cs%MEKE_min_gamma)
869 if (cs%use_old_lscale)
then
870 if (cs%Rd_as_max_scale)
then
871 lmixscale = min(ldeform, lgrid)
876 ue = sqrt( 2.0 * max( 0., barotrfac2*eke ) )
877 lrhines = sqrt( ue / max( beta, 1.e-30 ) )
878 if (cs%aEady > 0.)
then
879 leady = ue / max( sn, 1.e-15 )
883 if (cs%use_min_lscale)
then
885 if (cs%aDeform*ldeform > 0.) lmixscale = min(lmixscale,cs%aDeform*ldeform)
886 if (cs%aFrict *lfrict > 0.) lmixscale = min(lmixscale,cs%aFrict *lfrict)
887 if (cs%aRhines*lrhines > 0.) lmixscale = min(lmixscale,cs%aRhines*lrhines)
888 if (cs%aEady *leady > 0.) lmixscale = min(lmixscale,cs%aEady *leady)
889 if (cs%aGrid *lgrid > 0.) lmixscale = min(lmixscale,cs%aGrid *lgrid)
890 if (cs%Lfixed > 0.) lmixscale = min(lmixscale,cs%Lfixed)
893 if (cs%aDeform*ldeform > 0.) lmixscale = lmixscale + 1./(cs%aDeform*ldeform)
894 if (cs%aFrict *lfrict > 0.) lmixscale = lmixscale + 1./(cs%aFrict *lfrict)
895 if (cs%aRhines*lrhines > 0.) lmixscale = lmixscale + 1./(cs%aRhines*lrhines)
896 if (cs%aEady *leady > 0.) lmixscale = lmixscale + 1./(cs%aEady *leady)
897 if (cs%aGrid *lgrid > 0.) lmixscale = lmixscale + 1./(cs%aGrid *lgrid)
898 if (cs%Lfixed > 0.) lmixscale = lmixscale + 1./cs%Lfixed
899 if (lmixscale > 0.) lmixscale = 1. / lmixscale
903 end subroutine meke_lengthscales_0d
907 logical function meke_init(Time, G, US, param_file, diag, CS, MEKE, restart_CS)
908 type(time_type),
intent(in) :: time
912 type(
diag_ctrl),
target,
intent(inout) :: diag
920 integer :: i, j, is, ie, js, je, isd, ied, jsd, jed
921 logical :: laplacian, biharmonic, usevarmix, coldstart
923 # include "version_variable.h"
924 character(len=40) :: mdl =
"MOM_MEKE"
926 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
927 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
931 call get_param(param_file, mdl,
"USE_MEKE", meke_init, &
932 "If true, turns on the MEKE scheme which calculates "// &
933 "a sub-grid mesoscale eddy kinetic energy budget.", &
935 if (.not. meke_init)
return
937 if (.not.
associated(meke))
then
939 call mom_error(warning,
"MEKE_init called with NO associated "// &
940 "MEKE-type structure.")
943 if (
associated(cs))
then
944 call mom_error(warning, &
945 "MEKE_init called with an associated control structure.")
947 else ;
allocate(cs) ;
endif
949 call mom_mesg(
"MEKE_init: reading parameters ", 5)
952 call get_param(param_file, mdl,
"MEKE_DAMPING", cs%MEKE_damping, &
953 "The local depth-independent MEKE dissipation rate.", &
954 units=
"s-1", default=0.0)
955 call get_param(param_file, mdl,
"MEKE_CD_SCALE", cs%MEKE_Cd_scale, &
956 "The ratio of the bottom eddy velocity to the column mean "//&
957 "eddy velocity, i.e. sqrt(2*MEKE). This should be less than 1 "//&
958 "to account for the surface intensification of MEKE.", &
959 units=
"nondim", default=0.)
960 call get_param(param_file, mdl,
"MEKE_CB", cs%MEKE_Cb, &
961 "A coefficient in the expression for the ratio of bottom projected "//&
962 "eddy energy and mean column energy (see Jansen et al. 2015).",&
963 units=
"nondim", default=25.)
964 call get_param(param_file, mdl,
"MEKE_MIN_GAMMA2", cs%MEKE_min_gamma, &
965 "The minimum allowed value of gamma_b^2.",&
966 units=
"nondim", default=0.0001)
967 call get_param(param_file, mdl,
"MEKE_CT", cs%MEKE_Ct, &
968 "A coefficient in the expression for the ratio of barotropic "//&
969 "eddy energy and mean column energy (see Jansen et al. 2015).",&
970 units=
"nondim", default=50.)
971 call get_param(param_file, mdl,
"MEKE_GMCOEFF", cs%MEKE_GMcoeff, &
972 "The efficiency of the conversion of potential energy "//&
973 "into MEKE by the thickness mixing parameterization. "//&
974 "If MEKE_GMCOEFF is negative, this conversion is not "//&
975 "used or calculated.", units=
"nondim", default=-1.0)
976 call get_param(param_file, mdl,
"MEKE_GEOMETRIC", cs%MEKE_GEOMETRIC, &
977 "If MEKE_GEOMETRIC is true, uses the GM coefficient formulation "//&
978 "from the GEOMETRIC framework (Marshall et al., 2012).", default=.false.)
979 call get_param(param_file, mdl,
"MEKE_FRCOEFF", cs%MEKE_FrCoeff, &
980 "The efficiency of the conversion of mean energy into "//&
981 "MEKE. If MEKE_FRCOEFF is negative, this conversion "//&
982 "is not used or calculated.", units=
"nondim", default=-1.0)
983 call get_param(param_file, mdl,
"MEKE_GMECOEFF", cs%MEKE_GMECoeff, &
984 "The efficiency of the conversion of MEKE into mean energy "//&
985 "by GME. If MEKE_GMECOEFF is negative, this conversion "//&
986 "is not used or calculated.", units=
"nondim", default=-1.0)
987 call get_param(param_file, mdl,
"MEKE_BGSRC", cs%MEKE_BGsrc, &
988 "A background energy source for MEKE.", units=
"W kg-1", &
990 call get_param(param_file, mdl,
"MEKE_KH", cs%MEKE_Kh, &
991 "A background lateral diffusivity of MEKE. "//&
992 "Use a negative value to not apply lateral diffusion to MEKE.", &
993 units=
"m2 s-1", default=-1.0)
994 call get_param(param_file, mdl,
"MEKE_K4", cs%MEKE_K4, &
995 "A lateral bi-harmonic diffusivity of MEKE. "//&
996 "Use a negative value to not apply bi-harmonic diffusion to MEKE.", &
997 units=
"m4 s-1", default=-1.0)
998 call get_param(param_file, mdl,
"MEKE_DTSCALE", cs%MEKE_dtScale, &
999 "A scaling factor to accelerate the time evolution of MEKE.", &
1000 units=
"nondim", default=1.0)
1001 call get_param(param_file, mdl,
"MEKE_KHCOEFF", cs%MEKE_KhCoeff, &
1002 "A scaling factor in the expression for eddy diffusivity "//&
1003 "which is otherwise proportional to the MEKE velocity- "//&
1004 "scale times an eddy mixing-length. This factor "//&
1005 "must be >0 for MEKE to contribute to the thickness/ "//&
1006 "and tracer diffusivity in the rest of the model.", &
1007 units=
"nondim", default=1.0)
1008 call get_param(param_file, mdl,
"MEKE_USCALE", cs%MEKE_Uscale, &
1009 "The background velocity that is combined with MEKE to "//&
1010 "calculate the bottom drag.", units=
"m s-1", default=0.0)
1011 call get_param(param_file, mdl,
"MEKE_JANSEN15_DRAG", cs%Jansen15_drag, &
1012 "If true, use the bottom drag formulation from Jansen et al. (2015) "//&
1013 "to calculate the drag acting on MEKE.", default=.false.)
1014 call get_param(param_file, mdl,
"MEKE_GM_SRC_ALT", cs%GM_src_alt, &
1015 "If true, use the GM energy conversion form S^2*N^2*kappa rather "//&
1016 "than the streamfunction for the MEKE GM source term.", default=.false.)
1017 call get_param(param_file, mdl,
"MEKE_VISC_DRAG", cs%visc_drag, &
1018 "If true, use the vertvisc_type to calculate the bottom "//&
1019 "drag acting on MEKE.", default=.true.)
1020 call get_param(param_file, mdl,
"MEKE_KHTH_FAC", meke%KhTh_fac, &
1021 "A factor that maps MEKE%Kh to KhTh.", units=
"nondim", &
1023 call get_param(param_file, mdl,
"MEKE_KHTR_FAC", meke%KhTr_fac, &
1024 "A factor that maps MEKE%Kh to KhTr.", units=
"nondim", &
1026 call get_param(param_file, mdl,
"MEKE_KHMEKE_FAC", cs%KhMEKE_Fac, &
1027 "A factor that maps MEKE%Kh to Kh for MEKE itself.", &
1028 units=
"nondim", default=0.0)
1029 call get_param(param_file, mdl,
"MEKE_OLD_LSCALE", cs%use_old_lscale, &
1030 "If true, use the old formula for length scale which is "//&
1031 "a function of grid spacing and deformation radius.", &
1033 call get_param(param_file, mdl,
"MEKE_MIN_LSCALE", cs%use_min_lscale, &
1034 "If true, use a strict minimum of provided length scales "//&
1035 "rather than harmonic mean.", &
1037 call get_param(param_file, mdl,
"MEKE_RD_MAX_SCALE", cs%Rd_as_max_scale, &
1038 "If true, the length scale used by MEKE is the minimum of "//&
1039 "the deformation radius or grid-spacing. Only used if "//&
1040 "MEKE_OLD_LSCALE=True", units=
"nondim", default=.false.)
1041 call get_param(param_file, mdl,
"MEKE_VISCOSITY_COEFF_KU", cs%viscosity_coeff_Ku, &
1042 "If non-zero, is the scaling coefficient in the expression for"//&
1043 "viscosity used to parameterize harmonic lateral momentum mixing by"//&
1044 "unresolved eddies represented by MEKE. Can be negative to"//&
1045 "represent backscatter from the unresolved eddies.", &
1046 units=
"nondim", default=0.0)
1047 call get_param(param_file, mdl,
"MEKE_VISCOSITY_COEFF_AU", cs%viscosity_coeff_Au, &
1048 "If non-zero, is the scaling coefficient in the expression for"//&
1049 "viscosity used to parameterize biharmonic lateral momentum mixing by"//&
1050 "unresolved eddies represented by MEKE. Can be negative to"//&
1051 "represent backscatter from the unresolved eddies.", &
1052 units=
"nondim", default=0.0)
1053 call get_param(param_file, mdl,
"MEKE_FIXED_MIXING_LENGTH", cs%Lfixed, &
1054 "If positive, is a fixed length contribution to the expression "//&
1055 "for mixing length used in MEKE-derived diffusivity.", &
1056 units=
"m", default=0.0)
1057 call get_param(param_file, mdl,
"MEKE_ALPHA_DEFORM", cs%aDeform, &
1058 "If positive, is a coefficient weighting the deformation scale "//&
1059 "in the expression for mixing length used in MEKE-derived diffusivity.", &
1060 units=
"nondim", default=0.0)
1061 call get_param(param_file, mdl,
"MEKE_ALPHA_RHINES", cs%aRhines, &
1062 "If positive, is a coefficient weighting the Rhines scale "//&
1063 "in the expression for mixing length used in MEKE-derived diffusivity.", &
1064 units=
"nondim", default=0.05)
1065 call get_param(param_file, mdl,
"MEKE_ALPHA_EADY", cs%aEady, &
1066 "If positive, is a coefficient weighting the Eady length scale "//&
1067 "in the expression for mixing length used in MEKE-derived diffusivity.", &
1068 units=
"nondim", default=0.05)
1069 call get_param(param_file, mdl,
"MEKE_ALPHA_FRICT", cs%aFrict, &
1070 "If positive, is a coefficient weighting the frictional arrest scale "//&
1071 "in the expression for mixing length used in MEKE-derived diffusivity.", &
1072 units=
"nondim", default=0.0)
1073 call get_param(param_file, mdl,
"MEKE_ALPHA_GRID", cs%aGrid, &
1074 "If positive, is a coefficient weighting the grid-spacing as a scale "//&
1075 "in the expression for mixing length used in MEKE-derived diffusivity.", &
1076 units=
"nondim", default=0.0)
1077 call get_param(param_file, mdl,
"MEKE_COLD_START", coldstart, &
1078 "If true, initialize EKE to zero. Otherwise a local equilibrium solution "//&
1079 "is used as an initial condition for EKE.", default=.false.)
1080 call get_param(param_file, mdl,
"MEKE_BACKSCAT_RO_C", meke%backscatter_Ro_c, &
1081 "The coefficient in the Rossby number function for scaling the biharmonic "//&
1082 "frictional energy source. Setting to non-zero enables the Rossby number function.", &
1083 units=
"nondim", default=0.0)
1084 call get_param(param_file, mdl,
"MEKE_BACKSCAT_RO_POW", meke%backscatter_Ro_pow, &
1085 "The power in the Rossby number function for scaling the biharmonic "//&
1086 "frictional energy source.", units=
"nondim", default=0.0)
1087 call get_param(param_file, mdl,
"MEKE_ADVECTION_FACTOR", cs%MEKE_advection_factor, &
1088 "A scale factor in front of advection of eddy energy. Zero turns advection off. "//&
1089 "Using unity would be normal but other values could accommodate a mismatch "//&
1090 "between the advecting barotropic flow and the vertical structure of MEKE.", &
1091 units=
"nondim", default=0.0)
1092 call get_param(param_file, mdl,
"MEKE_TOPOGRAPHIC_BETA", cs%MEKE_topographic_beta, &
1093 "A scale factor to determine how much topographic beta is weighed in " //&
1094 "computing beta in the expression of Rhines scale. Use 1 if full "//&
1095 "topographic beta effect is considered; use 0 if it's completely ignored.", &
1096 units=
"nondim", default=0.0)
1099 call get_param(param_file, mdl,
"CDRAG", cs%cdrag, &
1100 "CDRAG is the drag coefficient relating the magnitude of "//&
1101 "the velocity field to the bottom stress.", units=
"nondim", &
1103 call get_param(param_file, mdl,
"LAPLACIAN", laplacian, default=.false., do_not_log=.true.)
1104 call get_param(param_file, mdl,
"BIHARMONIC", biharmonic, default=.false., do_not_log=.true.)
1106 if (cs%viscosity_coeff_Ku/=0. .and. .not. laplacian)
call mom_error(fatal, &
1107 "LAPLACIAN must be true if MEKE_VISCOSITY_COEFF_KU is true.")
1109 if (cs%viscosity_coeff_Au/=0. .and. .not. biharmonic)
call mom_error(fatal, &
1110 "BIHARMONIC must be true if MEKE_VISCOSITY_COEFF_AU is true.")
1112 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false., do_not_log=.true.)
1115 cs%kh_flux_enabled = .false.
1116 if ((cs%MEKE_KH >= 0.0) .or. (cs%KhMEKE_FAC > 0.0) .or. (cs%MEKE_advection_factor > 0.0)) &
1117 cs%kh_flux_enabled = .true.
1121 cs%id_MEKE = register_diag_field(
'ocean_model',
'MEKE', diag%axesT1, time, &
1122 'Mesoscale Eddy Kinetic Energy',
'm2 s-2')
1123 if (.not.
associated(meke%MEKE)) cs%id_MEKE = -1
1124 cs%id_Kh = register_diag_field(
'ocean_model',
'MEKE_KH', diag%axesT1, time, &
1125 'MEKE derived diffusivity',
'm2 s-1')
1126 if (.not.
associated(meke%Kh)) cs%id_Kh = -1
1127 cs%id_Ku = register_diag_field(
'ocean_model',
'MEKE_KU', diag%axesT1, time, &
1128 'MEKE derived lateral viscosity',
'm2 s-1', conversion=us%s_to_T)
1129 if (.not.
associated(meke%Ku)) cs%id_Ku = -1
1130 cs%id_Au = register_diag_field(
'ocean_model',
'MEKE_AU', diag%axesT1, time, &
1131 'MEKE derived lateral biharmonic viscosity',
'm4 s-1', conversion=us%s_to_T)
1132 if (.not.
associated(meke%Au)) cs%id_Au = -1
1133 cs%id_Ue = register_diag_field(
'ocean_model',
'MEKE_Ue', diag%axesT1, time, &
1134 'MEKE derived eddy-velocity scale',
'm s-1')
1135 if (.not.
associated(meke%MEKE)) cs%id_Ue = -1
1136 cs%id_Ub = register_diag_field(
'ocean_model',
'MEKE_Ub', diag%axesT1, time, &
1137 'MEKE derived bottom eddy-velocity scale',
'm s-1')
1138 if (.not.
associated(meke%MEKE)) cs%id_Ub = -1
1139 cs%id_Ut = register_diag_field(
'ocean_model',
'MEKE_Ut', diag%axesT1, time, &
1140 'MEKE derived barotropic eddy-velocity scale',
'm s-1')
1141 if (.not.
associated(meke%MEKE)) cs%id_Ut = -1
1142 cs%id_src = register_diag_field(
'ocean_model',
'MEKE_src', diag%axesT1, time, &
1143 'MEKE energy source',
'm2 s-3')
1144 cs%id_decay = register_diag_field(
'ocean_model',
'MEKE_decay', diag%axesT1, time, &
1145 'MEKE decay rate',
's-1')
1146 cs%id_GM_src = register_diag_field(
'ocean_model',
'MEKE_GM_src', diag%axesT1, time, &
1147 'MEKE energy available from thickness mixing',
'W m-2')
1148 if (.not.
associated(meke%GM_src)) cs%id_GM_src = -1
1149 cs%id_mom_src = register_diag_field(
'ocean_model',
'MEKE_mom_src',diag%axesT1, time, &
1150 'MEKE energy available from momentum',
'W m-2')
1151 if (.not.
associated(meke%mom_src)) cs%id_mom_src = -1
1152 cs%id_GME_snk = register_diag_field(
'ocean_model',
'MEKE_GME_snk',diag%axesT1, time, &
1153 'MEKE energy lost to GME backscatter',
'W m-2')
1154 if (.not.
associated(meke%GME_snk)) cs%id_GME_snk = -1
1155 cs%id_Le = register_diag_field(
'ocean_model',
'MEKE_Le', diag%axesT1, time, &
1156 'Eddy mixing length used in the MEKE derived eddy diffusivity',
'm')
1157 cs%id_Lrhines = register_diag_field(
'ocean_model',
'MEKE_Lrhines', diag%axesT1, time, &
1158 'Rhines length scale used in the MEKE derived eddy diffusivity',
'm')
1159 cs%id_Leady = register_diag_field(
'ocean_model',
'MEKE_Leady', diag%axesT1, time, &
1160 'Eady length scale used in the MEKE derived eddy diffusivity',
'm')
1161 cs%id_gamma_b = register_diag_field(
'ocean_model',
'MEKE_gamma_b', diag%axesT1, time, &
1162 'Ratio of bottom-projected eddy velocity to column-mean eddy velocity',
'nondim')
1163 cs%id_gamma_t = register_diag_field(
'ocean_model',
'MEKE_gamma_t', diag%axesT1, time, &
1164 'Ratio of barotropic eddy velocity to column-mean eddy velocity',
'nondim')
1166 if (cs%kh_flux_enabled)
then
1167 cs%id_KhMEKE_u = register_diag_field(
'ocean_model',
'KHMEKE_u', diag%axesCu1, time, &
1168 'Zonal diffusivity of MEKE',
'm2 s-1')
1169 cs%id_KhMEKE_v = register_diag_field(
'ocean_model',
'KHMEKE_v', diag%axesCv1, time, &
1170 'Meridional diffusivity of MEKE',
'm2 s-1')
1173 cs%id_clock_pass = cpu_clock_id(
'(Ocean continuity halo updates)', grain=clock_routine)
1179 if (coldstart) cs%initialize = .false.
1180 if (cs%initialize)
call mom_error(warning, &
1181 "MEKE_init: Initializing MEKE with a local equilibrium balance.")
1186 if ((us%s_to_T_restart /= 0.0) .and. (us%s_to_T_restart /= us%s_to_T)) &
1187 i_t_rescale = us%s_to_T_restart / us%s_to_T
1189 if (i_t_rescale /= 1.0)
then
1190 if (
associated(meke%Ku))
then ;
if (
query_initialized(meke%Ku,
"MEKE_Ku", restart_cs))
then
1191 do j=js,je ;
do i=is,ie
1192 meke%Ku(i,j) = i_t_rescale * meke%Ku(i,j)
1195 if (
associated(meke%Au))
then ;
if (
query_initialized(meke%Au,
"MEKE_Au", restart_cs))
then
1196 do j=js,je ;
do i=is,ie
1197 meke%Au(i,j) = i_t_rescale * meke%Au(i,j)
1203 if (
associated(meke%MEKE))
then
1205 if (
associated(meke%Kh_diff))
call create_group_pass(cs%pass_MEKE, meke%Kh_diff, g%Domain)
1206 if (.not.cs%initialize)
call do_group_pass(cs%pass_MEKE, g%Domain)
1212 if (
associated(meke%Kh) .or.
associated(meke%Ku) .or.
associated(meke%Au)) &
1213 call do_group_pass(cs%pass_Kh, g%Domain)
1215 end function meke_init
1218 subroutine meke_alloc_register_restart(HI, param_file, MEKE, restart_CS)
1226 real :: meke_gmcoeff, meke_frcoeff, meke_gmecoeff, meke_khcoeff, meke_visccoeff_ku, meke_visccoeff_au
1227 logical :: use_kh_in_meke
1229 integer :: isd, ied, jsd, jed
1232 usemeke = .false.;
call read_param(param_file,
"USE_MEKE",usemeke)
1235 meke_gmcoeff =-1.;
call read_param(param_file,
"MEKE_GMCOEFF",meke_gmcoeff)
1236 meke_frcoeff =-1.;
call read_param(param_file,
"MEKE_FRCOEFF",meke_frcoeff)
1237 meke_gmecoeff =-1.;
call read_param(param_file,
"MEKE_GMECOEFF",meke_gmecoeff)
1238 meke_khcoeff =1.;
call read_param(param_file,
"MEKE_KHCOEFF",meke_khcoeff)
1239 meke_visccoeff_ku =0.;
call read_param(param_file,
"MEKE_VISCOSITY_COEFF_KU",meke_visccoeff_ku)
1240 meke_visccoeff_au =0.;
call read_param(param_file,
"MEKE_VISCOSITY_COEFF_AU",meke_visccoeff_au)
1241 use_kh_in_meke = .false.;
call read_param(param_file,
"USE_KH_IN_MEKE", use_kh_in_meke)
1243 if (
associated(meke))
then
1244 call mom_error(warning,
"MEKE_alloc_register_restart called with an associated "// &
1247 else;
allocate(meke);
endif
1249 if (.not. usemeke)
return
1252 call mom_mesg(
"MEKE_alloc_register_restart: allocating and registering", 5)
1253 isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed
1254 allocate(meke%MEKE(isd:ied,jsd:jed)) ; meke%MEKE(:,:) = 0.0
1255 vd = var_desc(
"MEKE",
"m2 s-2", hor_grid=
'h', z_grid=
'1', &
1256 longname=
"Mesoscale Eddy Kinetic Energy")
1258 if (meke_gmcoeff>=0.)
then
1259 allocate(meke%GM_src(isd:ied,jsd:jed)) ; meke%GM_src(:,:) = 0.0
1261 if (meke_frcoeff>=0. .or. meke_gmecoeff>=0.)
then
1262 allocate(meke%mom_src(isd:ied,jsd:jed)) ; meke%mom_src(:,:) = 0.0
1264 if (meke_gmecoeff>=0.)
then
1265 allocate(meke%GME_snk(isd:ied,jsd:jed)) ; meke%GME_snk(:,:) = 0.0
1267 if (meke_khcoeff>=0.)
then
1268 allocate(meke%Kh(isd:ied,jsd:jed)) ; meke%Kh(:,:) = 0.0
1269 vd = var_desc(
"MEKE_Kh",
"m2 s-1", hor_grid=
'h', z_grid=
'1', &
1270 longname=
"Lateral diffusivity from Mesoscale Eddy Kinetic Energy")
1273 allocate(meke%Rd_dx_h(isd:ied,jsd:jed)) ; meke%Rd_dx_h(:,:) = 0.0
1274 if (meke_visccoeff_ku/=0.)
then
1275 allocate(meke%Ku(isd:ied,jsd:jed)) ; meke%Ku(:,:) = 0.0
1276 vd = var_desc(
"MEKE_Ku",
"m2 s-1", hor_grid=
'h', z_grid=
'1', &
1277 longname=
"Lateral viscosity from Mesoscale Eddy Kinetic Energy")
1280 if (use_kh_in_meke)
then
1281 allocate(meke%Kh_diff(isd:ied,jsd:jed)) ; meke%Kh_diff(:,:) = 0.0
1282 vd = var_desc(
"MEKE_Kh_diff",
"m2 s-1",hor_grid=
'h',z_grid=
'1', &
1283 longname=
"Copy of thickness diffusivity for diffusing MEKE")
1287 if (meke_visccoeff_au/=0.)
then
1288 allocate(meke%Au(isd:ied,jsd:jed)) ; meke%Au(:,:) = 0.0
1289 vd = var_desc(
"MEKE_Au",
"m4 s-1", hor_grid=
'h', z_grid=
'1', &
1290 longname=
"Lateral biharmonic viscosity from Mesoscale Eddy Kinetic Energy")
1294 end subroutine meke_alloc_register_restart
1298 subroutine meke_end(MEKE, CS)
1302 if (
associated(cs))
deallocate(cs)
1304 if (.not.
associated(meke))
return
1306 if (
associated(meke%MEKE))
deallocate(meke%MEKE)
1307 if (
associated(meke%GM_src))
deallocate(meke%GM_src)
1308 if (
associated(meke%mom_src))
deallocate(meke%mom_src)
1309 if (
associated(meke%GME_snk))
deallocate(meke%GME_snk)
1310 if (
associated(meke%Kh))
deallocate(meke%Kh)
1311 if (
associated(meke%Kh_diff))
deallocate(meke%Kh_diff)
1312 if (
associated(meke%Ku))
deallocate(meke%Ku)
1313 if (
associated(meke%Au))
deallocate(meke%Au)
1316 end subroutine meke_end