23 implicit none ;
private 25 #include <MOM_memory.h> 27 public thickness_diffuse, thickness_diffuse_init, thickness_diffuse_end
29 public thickness_diffuse_get_kh
39 real :: khth_slope_cff
46 logical :: thickness_diffuse
47 logical :: use_fgnv_streamfn
56 logical :: detangle_interfaces
64 logical :: use_gme_thickness_diffuse
66 logical :: meke_geometric
68 real :: meke_geometric_alpha
70 real :: meke_geometric_epsilon
72 logical :: meke_geom_answers_2018
75 logical :: use_kh_in_meke
78 logical :: use_gm_work_bug
80 real :: stanley_det_coeff
85 real,
pointer :: gmwork(:,:) => null()
86 real,
pointer :: diagslopex(:,:,:) => null()
87 real,
pointer :: diagslopey(:,:,:) => null()
89 real,
dimension(:,:,:),
pointer :: &
95 integer :: id_uhgm = -1, id_vhgm = -1, id_gmwork = -1
96 integer :: id_kh_u = -1, id_kh_v = -1, id_kh_t = -1
97 integer :: id_kh_u1 = -1, id_kh_v1 = -1, id_kh_t1 = -1
98 integer :: id_slope_x = -1, id_slope_y = -1
99 integer :: id_sfn_unlim_x = -1, id_sfn_unlim_y = -1, id_sfn_x = -1, id_sfn_y = -1
108 subroutine thickness_diffuse(h, uhtr, vhtr, tv, dt, G, GV, US, MEKE, VarMix, CDp, CS)
112 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
113 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhtr
115 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhtr
118 real,
intent(in) :: dt
124 real :: e(szi_(g), szj_(g), szk_(g)+1)
126 real :: uhD(szib_(g), szj_(g), szk_(g))
127 real :: vhD(szi_(g), szjb_(g), szk_(g))
129 real,
dimension(SZIB_(G), SZJ_(G), SZK_(G)+1) :: &
135 real,
dimension(SZI_(G), SZJB_(G), SZK_(G)+1) :: &
141 real,
dimension(SZI_(G), SZJ_(G), SZK_(G)) :: &
144 real,
dimension(SZIB_(G), SZJ_(G)) :: &
146 real,
dimension(SZI_(G), SZJB_(G)) :: &
148 real :: Khth_Loc_u(szib_(g), szj_(g))
149 real :: Khth_Loc_v(szi_(g), szjb_(g))
150 real :: Khth_Loc(szib_(g), szjb_(g))
153 real,
dimension(:,:),
pointer :: cg1 => null()
154 logical :: use_VarMix, Resoln_scaled, Depth_scaled, use_stored_slopes, khth_use_ebt_struct, use_Visbeck
155 logical :: use_QG_Leith
156 integer :: i, j, k, is, ie, js, je, nz
157 real :: hu(szi_(g), szj_(g))
158 real :: hv(szi_(g), szj_(g))
159 real :: KH_u_lay(szi_(g), szj_(g))
160 real :: KH_v_lay(szi_(g), szj_(g))
162 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_thickness_diffuse: "//&
163 "Module must be initialized before it is used.")
165 if ((.not.cs%thickness_diffuse) .or. &
166 .not.( cs%Khth > 0.0 .or.
associated(varmix) .or.
associated(meke) ) )
return 168 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
169 h_neglect = gv%H_subroundoff
171 if (
associated(meke))
then 172 if (
associated(meke%GM_src))
then 173 do j=js,je ;
do i=is,ie ; meke%GM_src(i,j) = 0. ;
enddo ;
enddo 177 use_varmix = .false. ; resoln_scaled = .false. ; use_stored_slopes = .false.
178 khth_use_ebt_struct = .false. ; use_visbeck = .false. ; use_qg_leith = .false.
179 depth_scaled = .false.
181 if (
associated(varmix))
then 182 use_varmix = varmix%use_variable_mixing .and. (cs%KHTH_Slope_Cff > 0.)
183 resoln_scaled = varmix%Resoln_scaled_KhTh
184 depth_scaled = varmix%Depth_scaled_KhTh
185 use_stored_slopes = varmix%use_stored_slopes
186 khth_use_ebt_struct = varmix%khth_use_ebt_struct
187 use_visbeck = varmix%use_Visbeck
188 use_qg_leith = varmix%use_QG_Leith_GM
189 if (
associated(varmix%cg1)) cg1 => varmix%cg1
196 do j=js,je ;
do i=is-1,ie
197 kh_u_cfl(i,j) = (0.25*cs%max_Khth_CFL) / &
198 (dt * (g%IdxCu(i,j)*g%IdxCu(i,j) + g%IdyCu(i,j)*g%IdyCu(i,j)))
201 do j=js-1,je ;
do i=is,ie
202 kh_v_cfl(i,j) = (0.25*cs%max_Khth_CFL) / &
203 (dt * (g%IdxCv(i,j)*g%IdxCv(i,j) + g%IdyCv(i,j)*g%IdyCv(i,j)))
207 call find_eta(h, tv, g, gv, us, e, halo_size=1)
216 do j=js,je;
do i=is-1,ie
217 khth_loc_u(i,j) = cs%Khth
221 if (use_visbeck)
then 223 do j=js,je ;
do i=is-1,ie
224 khth_loc_u(i,j) = khth_loc_u(i,j) + &
225 cs%KHTH_Slope_Cff*varmix%L2u(i,j) * varmix%SN_u(i,j)
230 if (
associated(meke))
then ;
if (
associated(meke%Kh))
then 231 if (cs%MEKE_GEOMETRIC)
then 233 do j=js,je ;
do i=is-1,ie
234 khth_loc_u(i,j) = khth_loc_u(i,j) + g%mask2dCu(i,j) * cs%MEKE_GEOMETRIC_alpha * &
235 0.5*(meke%MEKE(i,j)+meke%MEKE(i+1,j)) / &
236 (varmix%SN_u(i,j) + cs%MEKE_GEOMETRIC_epsilon)
239 do j=js,je ;
do i=is-1,ie
240 khth_loc_u(i,j) = khth_loc_u(i,j) + meke%KhTh_fac*sqrt(meke%Kh(i,j)*meke%Kh(i+1,j))
245 if (resoln_scaled)
then 247 do j=js,je;
do i=is-1,ie
248 khth_loc_u(i,j) = khth_loc_u(i,j) * varmix%Res_fn_u(i,j)
252 if (depth_scaled)
then 254 do j=js,je;
do i=is-1,ie
255 khth_loc_u(i,j) = khth_loc_u(i,j) * varmix%Depth_fn_u(i,j)
259 if (cs%Khth_Max > 0)
then 261 do j=js,je;
do i=is-1,ie
262 khth_loc_u(i,j) = max(cs%Khth_Min, min(khth_loc_u(i,j), cs%Khth_Max))
266 do j=js,je;
do i=is-1,ie
267 khth_loc_u(i,j) = max(cs%Khth_Min, khth_loc_u(i,j))
271 do j=js,je;
do i=is-1,ie
272 kh_u(i,j,1) = min(kh_u_cfl(i,j), khth_loc_u(i,j))
275 if (khth_use_ebt_struct)
then 277 do k=2,nz+1 ;
do j=js,je ;
do i=is-1,ie
278 kh_u(i,j,k) = kh_u(i,j,1) * 0.5 * ( varmix%ebt_struct(i,j,k-1) + varmix%ebt_struct(i+1,j,k-1) )
279 enddo ;
enddo ;
enddo 282 do k=2,nz+1 ;
do j=js,je ;
do i=is-1,ie
283 kh_u(i,j,k) = kh_u(i,j,1)
284 enddo ;
enddo ;
enddo 288 if (use_qg_leith)
then 290 do k=1,nz ;
do j=js,je ;
do i=is-1,ie
291 kh_u(i,j,k) = varmix%KH_u_QG(i,j,k)
292 enddo ;
enddo ;
enddo 296 if (cs%use_GME_thickness_diffuse)
then 298 do k=1,nz+1 ;
do j=js,je ;
do i=is-1,ie
299 cs%KH_u_GME(i,j,k) = kh_u(i,j,k)
300 enddo ;
enddo ;
enddo 304 do j=js-1,je ;
do i=is,ie
305 khth_loc_v(i,j) = cs%Khth
309 if (use_visbeck)
then 311 do j=js-1,je ;
do i=is,ie
312 khth_loc_v(i,j) = khth_loc_v(i,j) + cs%KHTH_Slope_Cff*varmix%L2v(i,j)*varmix%SN_v(i,j)
316 if (
associated(meke))
then ;
if (
associated(meke%Kh))
then 317 if (cs%MEKE_GEOMETRIC)
then 319 do j=js-1,je ;
do i=is,ie
320 khth_loc_v(i,j) = khth_loc_v(i,j) + g%mask2dCv(i,j) * cs%MEKE_GEOMETRIC_alpha * &
321 0.5*(meke%MEKE(i,j)+meke%MEKE(i,j+1)) / &
322 (varmix%SN_v(i,j) + cs%MEKE_GEOMETRIC_epsilon)
325 do j=js-1,je ;
do i=is,ie
326 khth_loc_v(i,j) = khth_loc_v(i,j) + meke%KhTh_fac*sqrt(meke%Kh(i,j)*meke%Kh(i,j+1))
331 if (resoln_scaled)
then 333 do j=js-1,je;
do i=is,ie
334 khth_loc_v(i,j) = khth_loc_v(i,j) * varmix%Res_fn_v(i,j)
338 if (depth_scaled)
then 340 do j=js-1,je ;
do i=is,ie
341 khth_loc_v(i,j) = khth_loc_v(i,j) * varmix%Depth_fn_v(i,j)
345 if (cs%Khth_Max > 0)
then 347 do j=js-1,je ;
do i=is,ie
348 khth_loc_v(i,j) = max(cs%Khth_Min, min(khth_loc_v(i,j), cs%Khth_Max))
352 do j=js-1,je ;
do i=is,ie
353 khth_loc_v(i,j) = max(cs%Khth_Min, khth_loc_v(i,j))
357 if (cs%max_Khth_CFL > 0.0)
then 359 do j=js-1,je ;
do i=is,ie
360 kh_v(i,j,1) = min(kh_v_cfl(i,j), khth_loc_v(i,j))
364 if (khth_use_ebt_struct)
then 366 do k=2,nz+1 ;
do j=js-1,je ;
do i=is,ie
367 kh_v(i,j,k) = kh_v(i,j,1) * 0.5 * ( varmix%ebt_struct(i,j,k-1) + varmix%ebt_struct(i,j+1,k-1) )
368 enddo ;
enddo ;
enddo 371 do k=2,nz+1 ;
do j=js-1,je ;
do i=is,ie
372 kh_v(i,j,k) = kh_v(i,j,1)
373 enddo ;
enddo ;
enddo 377 if (use_qg_leith)
then 379 do k=1,nz ;
do j=js-1,je ;
do i=is,ie
380 kh_v(i,j,k) = varmix%KH_v_QG(i,j,k)
381 enddo ;
enddo ;
enddo 385 if (cs%use_GME_thickness_diffuse)
then 387 do k=1,nz+1 ;
do j=js-1,je ;
do i=is,ie
388 cs%KH_v_GME(i,j,k) = kh_v(i,j,k)
389 enddo ;
enddo ;
enddo 392 if (
associated(meke))
then ;
if (
associated(meke%Kh))
then 393 if (cs%MEKE_GEOMETRIC)
then 394 if (cs%MEKE_GEOM_answers_2018)
then 396 do j=js,je ;
do i=is,ie
398 meke%Kh(i,j) = cs%MEKE_GEOMETRIC_alpha * meke%MEKE(i,j) / &
399 (0.25*(varmix%SN_u(i,j)+varmix%SN_u(i-1,j) + &
400 varmix%SN_v(i,j)+varmix%SN_v(i,j-1)) + &
401 cs%MEKE_GEOMETRIC_epsilon)
405 do j=js,je ;
do i=is,ie
407 meke%Kh(i,j) = cs%MEKE_GEOMETRIC_alpha * meke%MEKE(i,j) / &
408 (0.25*((varmix%SN_u(i,j)+varmix%SN_u(i-1,j)) + &
409 (varmix%SN_v(i,j)+varmix%SN_v(i,j-1))) + &
410 cs%MEKE_GEOMETRIC_epsilon)
418 do k=1,nz+1 ;
do j=js,je ;
do i=is-1,ie ; int_slope_u(i,j,k) = 0.0 ;
enddo ;
enddo ;
enddo 420 do k=1,nz+1 ;
do j=js-1,je ;
do i=is,ie ; int_slope_v(i,j,k) = 0.0 ;
enddo ;
enddo ;
enddo 423 if (cs%detangle_interfaces)
then 424 call add_detangling_kh(h, e, kh_u, kh_v, kh_u_cfl, kh_v_cfl, tv, dt, g, gv, us, &
425 cs, int_slope_u, int_slope_v)
429 call uvchksum(
"Kh_[uv]", kh_u, kh_v, g%HI, haloshift=0, &
430 scale=(us%L_to_m**2)*us%s_to_T, scalar_pair=.true.)
431 call uvchksum(
"int_slope_[uv]", int_slope_u, int_slope_v, g%HI, haloshift=0)
432 call hchksum(h,
"thickness_diffuse_1 h", g%HI, haloshift=1, scale=gv%H_to_m)
433 call hchksum(e,
"thickness_diffuse_1 e", g%HI, haloshift=1, scale=us%Z_to_m)
434 if (use_stored_slopes)
then 435 call uvchksum(
"VarMix%slope_[xy]", varmix%slope_x, varmix%slope_y, &
438 if (
associated(tv%eqn_of_state))
then 439 call hchksum(tv%T,
"thickness_diffuse T", g%HI, haloshift=1)
440 call hchksum(tv%S,
"thickness_diffuse S", g%HI, haloshift=1)
445 if (use_stored_slopes)
then 446 call thickness_diffuse_full(h, e, kh_u, kh_v, tv, uhd, vhd, cg1, dt, g, gv, us, meke, cs, &
447 int_slope_u, int_slope_v, varmix%slope_x, varmix%slope_y)
449 call thickness_diffuse_full(h, e, kh_u, kh_v, tv, uhd, vhd, cg1, dt, g, gv, us, meke, cs, &
450 int_slope_u, int_slope_v)
453 if (
associated(meke) .AND.
associated(varmix))
then 454 if (
associated(meke%Rd_dx_h) .and.
associated(varmix%Rd_dx_h))
then 456 do j=js,je ;
do i=is,ie
457 meke%Rd_dx_h(i,j) = varmix%Rd_dx_h(i,j)
463 if (query_averaging_enabled(cs%diag))
then 464 if (cs%id_uhGM > 0)
call post_data(cs%id_uhGM, uhd, cs%diag)
465 if (cs%id_vhGM > 0)
call post_data(cs%id_vhGM, vhd, cs%diag)
466 if (cs%id_GMwork > 0)
call post_data(cs%id_GMwork, cs%GMwork, cs%diag)
467 if (cs%id_KH_u > 0)
call post_data(cs%id_KH_u, kh_u, cs%diag)
468 if (cs%id_KH_v > 0)
call post_data(cs%id_KH_v, kh_v, cs%diag)
469 if (cs%id_KH_u1 > 0)
call post_data(cs%id_KH_u1, kh_u(:,:,1), cs%diag)
470 if (cs%id_KH_v1 > 0)
call post_data(cs%id_KH_v1, kh_v(:,:,1), cs%diag)
477 if (cs%id_KH_t > 0 .or. cs%id_KH_t1 > 0 .or. cs%Use_KH_in_MEKE)
then 481 do j=js,je ;
do i=is-1,ie
482 hu(i,j) = 2.0*h(i,j,k)*h(i+1,j,k)/(h(i,j,k)+h(i+1,j,k)+h_neglect)
483 if (hu(i,j) /= 0.0) hu(i,j) = 1.0
484 kh_u_lay(i,j) = 0.5*(kh_u(i,j,k)+kh_u(i,j,k+1))
486 do j=js-1,je ;
do i=is,ie
487 hv(i,j) = 2.0*h(i,j,k)*h(i,j+1,k)/(h(i,j,k)+h(i,j+1,k)+h_neglect)
488 if (hv(i,j) /= 0.0) hv(i,j) = 1.0
489 kh_v_lay(i,j) = 0.5*(kh_v(i,j,k)+kh_v(i,j,k+1))
492 do j=js,je ;
do i=is,ie
493 kh_t(i,j,k) = ((hu(i-1,j)*kh_u_lay(i-1,j)+hu(i,j)*kh_u_lay(i,j)) &
494 +(hv(i,j-1)*kh_v_lay(i,j-1)+hv(i,j)*kh_v_lay(i,j))) &
495 / (hu(i-1,j)+hu(i,j)+hv(i,j-1)+hv(i,j)+h_neglect)
499 if (cs%Use_KH_in_MEKE)
then 500 meke%Kh_diff(:,:) = 0.0
502 do j=js,je ;
do i=is,ie
503 meke%Kh_diff(i,j) = meke%Kh_diff(i,j) + kh_t(i,j,k) * h(i,j,k)
507 do j=js,je ;
do i=is,ie
508 meke%Kh_diff(i,j) = meke%Kh_diff(i,j) / max(1.0,g%bathyT(i,j))
512 if (cs%id_KH_t > 0)
call post_data(cs%id_KH_t, kh_t, cs%diag)
513 if (cs%id_KH_t1 > 0)
call post_data(cs%id_KH_t1, kh_t(:,:,1), cs%diag)
520 do j=js,je ;
do i=is-1,ie
521 uhtr(i,j,k) = uhtr(i,j,k) + uhd(i,j,k) * dt
522 if (
associated(cdp%uhGM)) cdp%uhGM(i,j,k) = uhd(i,j,k)
524 do j=js-1,je ;
do i=is,ie
525 vhtr(i,j,k) = vhtr(i,j,k) + vhd(i,j,k) * dt
526 if (
associated(cdp%vhGM)) cdp%vhGM(i,j,k) = vhd(i,j,k)
528 do j=js,je ;
do i=is,ie
529 h(i,j,k) = h(i,j,k) - dt * g%IareaT(i,j) * &
530 ((uhd(i,j,k) - uhd(i-1,j,k)) + (vhd(i,j,k) - vhd(i,j-1,k)))
531 if (h(i,j,k) < gv%Angstrom_H) h(i,j,k) = gv%Angstrom_H
538 call diag_update_remap_grids(cs%diag)
541 call uvchksum(
"thickness_diffuse [uv]hD", uhd, vhd, &
542 g%HI, haloshift=0, scale=gv%H_to_m*us%L_to_m**2*us%s_to_T)
543 call uvchksum(
"thickness_diffuse [uv]htr", uhtr, vhtr, &
544 g%HI, haloshift=0, scale=us%L_to_m**2*gv%H_to_m)
545 call hchksum(h,
"thickness_diffuse h", g%HI, haloshift=0, scale=gv%H_to_m)
548 end subroutine thickness_diffuse
553 subroutine thickness_diffuse_full(h, e, Kh_u, Kh_v, tv, uhD, vhD, cg1, dt, G, GV, US, MEKE, &
554 CS, int_slope_u, int_slope_v, slope_x, slope_y)
555 type(ocean_grid_type),
intent(in) :: G
556 type(verticalgrid_type),
intent(in) :: GV
557 type(unit_scale_type),
intent(in) :: US
558 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
559 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1),
intent(in) :: e
560 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)+1),
intent(in) :: Kh_u
562 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)+1),
intent(in) :: Kh_v
564 type(thermo_var_ptrs),
intent(in) :: tv
565 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(out) :: uhD
567 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(out) :: vhD
569 real,
dimension(:,:),
pointer :: cg1
570 real,
intent(in) :: dt
571 type(meke_type),
pointer :: MEKE
573 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)+1),
optional,
intent(in) :: int_slope_u
577 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)+1),
optional,
intent(in) :: int_slope_v
581 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)+1),
optional,
intent(in) :: slope_x
582 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)+1),
optional,
intent(in) :: slope_y
584 real,
dimension(SZI_(G), SZJ_(G), SZK_(G)) :: &
593 real,
dimension(SZI_(G), SZJB_(G), SZK_(G)+1) :: &
597 real,
dimension(SZIB_(G), SZJ_(G), SZK_(G)+1) :: &
601 real,
dimension(SZI_(G), SZJ_(G), SZK_(G)+1) :: &
604 real,
dimension(SZIB_(G)) :: &
608 real,
dimension(SZIB_(G)) :: scrap
609 real,
dimension(SZI_(G)) :: &
613 real :: uhtot(szib_(g), szj_(g))
614 real :: vhtot(szi_(g), szjb_(g))
615 real,
dimension(SZIB_(G)) :: &
619 real,
dimension(SZI_(G)) :: &
623 real :: Work_u(szib_(g), szj_(g))
624 real :: Work_v(szi_(g), szjb_(g))
633 real :: drdi_u(szib_(g), szk_(g))
634 real :: drdj_v(szi_(g), szk_(g))
635 real :: drdkDe_u(szib_(g),szk_(g)+1)
637 real :: drdkDe_v(szi_(g),szk_(g)+1)
639 real :: hg2A, hg2B, hg2L, hg2R
640 real :: haA, haB, haL, haR
642 real :: wtA, wtB, wtL, wtR
646 real :: c2_h_u(szib_(g), szk_(g)+1)
647 real :: c2_h_v(szi_(g), szk_(g)+1)
648 real :: hN2_u(szib_(g), szk_(g)+1)
649 real :: hN2_v(szi_(g), szk_(g)+1)
652 real :: Sfn_unlim_u(szib_(g), szk_(g)+1)
653 real :: Sfn_unlim_v(szi_(g), szk_(g)+1)
654 real :: slope2_Ratio_u(szib_(g), szk_(g)+1)
655 real :: slope2_Ratio_v(szi_(g), szk_(g)+1)
683 real,
dimension(SZI_(G), SZJ_(G), SZK_(G)) :: Tsgs2
685 real,
dimension(SZIB_(G), SZJ_(G), SZK_(G)+1) :: diag_sfn_x, diag_sfn_unlim_x
686 real,
dimension(SZI_(G), SZJB_(G), SZK_(G)+1) :: diag_sfn_y, diag_sfn_unlim_y
687 logical :: present_int_slope_u, present_int_slope_v
688 logical :: present_slope_x, present_slope_y, calc_derivatives
689 integer,
dimension(2) :: EOSdom_u
691 integer,
dimension(2) :: EOSdom_v
693 logical :: use_Stanley
694 integer :: is, ie, js, je, nz, IsdB, halo
696 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke ; isdb = g%IsdB
699 i_slope_max2 = 1.0 / (cs%slope_max**2)
700 g_scale = gv%g_Earth * gv%H_to_Z
702 h_neglect = gv%H_subroundoff ; h_neglect2 = h_neglect**2
703 dz_neglect = gv%H_subroundoff*gv%H_to_Z
704 g_rho0 = gv%g_Earth / gv%Rho0
705 n2_floor = cs%N2_floor*us%Z_to_L**2
707 use_eos =
associated(tv%eqn_of_state)
708 present_int_slope_u =
PRESENT(int_slope_u)
709 present_int_slope_v =
PRESENT(int_slope_v)
710 present_slope_x =
PRESENT(slope_x)
711 present_slope_y =
PRESENT(slope_y)
712 use_stanley = cs%Stanley_det_coeff >= 0.
714 nk_linear = max(gv%nkml, 1)
716 slope_x_pe(:,:,:) = 0.0
717 slope_y_pe(:,:,:) = 0.0
718 hn2_x_pe(:,:,:) = 0.0
719 hn2_y_pe(:,:,:) = 0.0
722 if (
associated(meke)) find_work =
associated(meke%GM_src)
723 find_work = (
associated(cs%GMwork) .or. find_work)
727 if (use_stanley) halo = 2
728 call vert_fill_ts(h, tv%T, tv%S, cs%kappa_smooth*dt, t, s, g, gv, halo, larger_h_denom=.true.)
731 if (cs%use_FGNV_streamfn .and. .not.
associated(cg1))
call mom_error(fatal, &
732 "cg1 must be associated when using FGNV streamfunction.")
740 do j=js-1,je+1 ;
do i=is-1,ie+1
741 h_avail_rsum(i,j,1) = 0.0
743 if (
associated(tv%p_surf))
then ; pres(i,j,1) = tv%p_surf(i,j) ;
endif 745 h_avail(i,j,1) = max(i4dt*g%areaT(i,j)*(h(i,j,1)-gv%Angstrom_H),0.0)
746 h_avail_rsum(i,j,2) = h_avail(i,j,1)
748 pres(i,j,2) = pres(i,j,1) + (gv%g_Earth*gv%H_to_RZ) * h(i,j,1)
750 if (use_stanley)
then 752 do k=1, nz ;
do j=js-1,je+1 ;
do i=is-1,ie+1
765 hl(1) = h(i,j,k) * g%mask2dT(i,j)
766 hl(2) = h(i-1,j,k) * g%mask2dCu(i-1,j)
767 hl(3) = h(i+1,j,k) * g%mask2dCu(i,j)
768 hl(4) = h(i,j-1,k) * g%mask2dCv(i,j-1)
769 hl(5) = h(i,j+1,k) * g%mask2dCv(i,j)
770 r_sm_h = 1. / ( ( hl(1) + ( ( hl(2) + hl(3) ) + ( hl(4) + hl(5) ) ) ) + gv%H_subroundoff )
772 tl(1) = t(i,j,k) ; tl(2) = t(i-1,j,k) ; tl(3) = t(i+1,j,k)
773 tl(4) = t(i,j-1,k) ; tl(5) = t(i,j+1,k)
774 mn_t = ( hl(1)*tl(1) + ( ( hl(2)*tl(2) + hl(3)*tl(3) ) + ( hl(4)*tl(4) + hl(5)*tl(5) ) ) ) * r_sm_h
776 tl(:) = tl(:) - mn_t ; mn_t = 0.
778 mn_t2 = ( hl(1)*tl(1)*tl(1) + ( ( hl(2)*tl(2)*tl(2) + hl(3)*tl(3)*tl(3) ) &
779 + ( hl(4)*tl(4)*tl(4) + hl(5)*tl(5)*tl(5) ) ) ) * r_sm_h
782 tsgs2(i,j,k) = cs%Stanley_det_coeff * max(0., mn_t2)
783 enddo ;
enddo ;
enddo 787 do k=2,nz ;
do i=is-1,ie+1
788 h_avail(i,j,k) = max(i4dt*g%areaT(i,j)*(h(i,j,k)-gv%Angstrom_H),0.0)
789 h_avail_rsum(i,j,k+1) = h_avail_rsum(i,j,k) + h_avail(i,j,k)
790 h_frac(i,j,k) = 0.0 ;
if (h_avail(i,j,k) > 0.0) &
791 h_frac(i,j,k) = h_avail(i,j,k) / h_avail_rsum(i,j,k+1)
792 pres(i,j,k+1) = pres(i,j,k) + (gv%g_Earth*gv%H_to_RZ) * h(i,j,k)
796 do j=js,je ;
do i=is-1,ie
797 uhtot(i,j) = 0.0 ; work_u(i,j) = 0.0
798 diag_sfn_x(i,j,1) = 0.0 ; diag_sfn_unlim_x(i,j,1) = 0.0
799 diag_sfn_x(i,j,nz+1) = 0.0 ; diag_sfn_unlim_x(i,j,nz+1) = 0.0
802 do j=js-1,je ;
do i=is,ie
803 vhtot(i,j) = 0.0 ; work_v(i,j) = 0.0
804 diag_sfn_y(i,j,1) = 0.0 ; diag_sfn_unlim_y(i,j,1) = 0.0
805 diag_sfn_y(i,j,nz+1) = 0.0 ; diag_sfn_unlim_y(i,j,nz+1) = 0.0
809 eosdom_u(1) = (is-1) - (g%IsdB-1) ; eosdom_u(2) = ie - (g%IsdB-1)
826 do i=is-1,ie ; hn2_u(i,1) = 0. ; hn2_u(i,nz+1) = 0. ;
enddo 828 if (find_work .and. .not.(use_eos))
then 829 drdia = 0.0 ; drdib = 0.0
830 drdkl = gv%Rlay(k) - gv%Rlay(k-1) ; drdkr = drdkl
833 calc_derivatives = use_eos .and. (k >= nk_linear) .and. &
834 (find_work .or. .not. present_slope_x .or. cs%use_FGNV_streamfn .or. use_stanley)
837 if (calc_derivatives)
then 839 pres_u(i) = 0.5*(pres(i,j,k) + pres(i+1,j,k))
840 t_u(i) = 0.25*((t(i,j,k) + t(i+1,j,k)) + (t(i,j,k-1) + t(i+1,j,k-1)))
841 s_u(i) = 0.25*((s(i,j,k) + s(i+1,j,k)) + (s(i,j,k-1) + s(i+1,j,k-1)))
843 call calculate_density_derivs(t_u, s_u, pres_u, drho_dt_u, drho_ds_u, &
844 tv%eqn_of_state, eosdom_u)
846 if (use_stanley)
then 849 call calculate_density_second_derivs(t_u, s_u, pres_u, &
850 scrap, scrap, drho_dt_dt_u, scrap, scrap, &
851 (is-isdb+1)-1, ie-is+2, tv%eqn_of_state)
855 if (calc_derivatives)
then 857 drdia = drho_dt_u(i) * (t(i+1,j,k-1)-t(i,j,k-1)) + &
858 drho_ds_u(i) * (s(i+1,j,k-1)-s(i,j,k-1))
859 drdib = drho_dt_u(i) * (t(i+1,j,k)-t(i,j,k)) + &
860 drho_ds_u(i) * (s(i+1,j,k)-s(i,j,k))
863 drdkl = (drho_dt_u(i) * (t(i,j,k)-t(i,j,k-1)) + &
864 drho_ds_u(i) * (s(i,j,k)-s(i,j,k-1)))
865 drdkr = (drho_dt_u(i) * (t(i+1,j,k)-t(i+1,j,k-1)) + &
866 drho_ds_u(i) * (s(i+1,j,k)-s(i+1,j,k-1)))
867 drdkde_u(i,k) = drdkr * e(i+1,j,k) - drdkl * e(i,j,k)
868 elseif (find_work)
then 869 drdkde_u(i,k) = drdkr * e(i+1,j,k) - drdkl * e(i,j,k)
871 if (use_stanley)
then 874 drdia = drdia + drho_dt_dt_u(i) * 0.5 * ( tsgs2(i+1,j,k-1)-tsgs2(i,j,k-1) )
875 drdib = drdib + drho_dt_dt_u(i) * 0.5 * ( tsgs2(i+1,j,k)-tsgs2(i,j,k) )
877 if (find_work) drdi_u(i,k) = drdib
879 if (k > nk_linear)
then 881 if (cs%use_FGNV_streamfn .or. find_work .or. .not.present_slope_x)
then 882 hg2l = h(i,j,k-1)*h(i,j,k) + h_neglect2
883 hg2r = h(i+1,j,k-1)*h(i+1,j,k) + h_neglect2
884 hal = 0.5*(h(i,j,k-1) + h(i,j,k)) + h_neglect
885 har = 0.5*(h(i+1,j,k-1) + h(i+1,j,k)) + h_neglect
886 if (gv%Boussinesq)
then 887 dzal = hal * gv%H_to_Z ; dzar = har * gv%H_to_Z
889 dzal = 0.5*(e(i,j,k-1) - e(i,j,k+1)) + dz_neglect
890 dzar = 0.5*(e(i+1,j,k-1) - e(i+1,j,k+1)) + dz_neglect
894 wtl = hg2l*(har*dzar) ; wtr = hg2r*(hal*dzal)
896 drdz = (wtl * drdkl + wtr * drdkr) / (dzal*wtl + dzar*wtr)
900 hg2a = h(i,j,k-1)*h(i+1,j,k-1) + h_neglect2
901 hg2b = h(i,j,k)*h(i+1,j,k) + h_neglect2
902 haa = 0.5*(h(i,j,k-1) + h(i+1,j,k-1)) + h_neglect
903 hab = 0.5*(h(i,j,k) + h(i+1,j,k)) + h_neglect
906 hn2_u(i,k) = (0.5 * gv%H_to_Z * ( hg2a / haa + hg2b / hab )) * &
907 max(drdz*g_rho0, n2_floor)
909 if (present_slope_x)
then 910 slope = slope_x(i,j,k)
911 slope2_ratio_u(i,k) = slope**2 * i_slope_max2
915 wta = hg2a*hab ; wtb = hg2b*haa
917 drdx = ((wta * drdia + wtb * drdib) / (wta + wtb) - &
918 drdz * (e(i,j,k)-e(i+1,j,k))) * g%IdxCu(i,j)
922 mag_grad2 = drdx**2 + (us%L_to_Z*drdz)**2
923 if (mag_grad2 > 0.0)
then 924 slope = drdx / sqrt(mag_grad2)
925 slope2_ratio_u(i,k) = slope**2 * i_slope_max2
928 slope2_ratio_u(i,k) = 1.0e20
934 if (present_int_slope_u)
then 935 slope = (1.0 - int_slope_u(i,j,k)) * slope + &
936 int_slope_u(i,j,k) * us%Z_to_L*((e(i+1,j,k)-e(i,j,k)) * g%IdxCu(i,j))
937 slope2_ratio_u(i,k) = (1.0 - int_slope_u(i,j,k)) * slope2_ratio_u(i,k)
940 slope_x_pe(i,j,k) = min(slope,cs%slope_max)
941 hn2_x_pe(i,j,k) = hn2_u(i,k)
942 if (cs%id_slope_x > 0) cs%diagSlopeX(i,j,k) = slope
945 sfn_unlim_u(i,k) = -((kh_u(i,j,k)*g%dy_Cu(i,j))*us%L_to_Z*slope)
949 if (sfn_unlim_u(i,k) > 0.0)
then 950 if (e(i,j,k) < e(i+1,j,nz+1))
then 951 sfn_unlim_u(i,k) = 0.0
953 elseif (e(i+1,j,nz+1) > e(i,j,k+1))
then 956 sfn_unlim_u(i,k) = sfn_unlim_u(i,k) * ((e(i,j,k) - e(i+1,j,nz+1)) / &
957 ((e(i,j,k) - e(i,j,k+1)) + dz_neglect))
960 if (e(i+1,j,k) < e(i,j,nz+1))
then ; sfn_unlim_u(i,k) = 0.0
961 elseif (e(i,j,nz+1) > e(i+1,j,k+1))
then 962 sfn_unlim_u(i,k) = sfn_unlim_u(i,k) * ((e(i+1,j,k) - e(i,j,nz+1)) / &
963 ((e(i+1,j,k) - e(i+1,j,k+1)) + dz_neglect))
968 if (present_slope_x)
then 969 slope = slope_x(i,j,k)
971 slope = us%Z_to_L*((e(i,j,k)-e(i+1,j,k))*g%IdxCu(i,j)) * g%mask2dCu(i,j)
973 if (cs%id_slope_x > 0) cs%diagSlopeX(i,j,k) = slope
974 sfn_unlim_u(i,k) = ((kh_u(i,j,k)*g%dy_Cu(i,j))*us%L_to_Z*slope)
975 hn2_u(i,k) = gv%g_prime(k)
978 hn2_u(i,k) = n2_floor * dz_neglect
979 sfn_unlim_u(i,k) = 0.
981 if (cs%id_sfn_unlim_x>0) diag_sfn_unlim_x(i,j,k) = sfn_unlim_u(i,k)
985 if (cs%use_FGNV_streamfn)
then 986 do k=1,nz ;
do i=is-1,ie ;
if (g%mask2dCu(i,j)>0.)
then 987 h_harm = max( h_neglect, &
988 2. * h(i,j,k) * h(i+1,j,k) / ( ( h(i,j,k) + h(i+1,j,k) ) + h_neglect ) )
989 c2_h_u(i,k) = cs%FGNV_scale * &
990 ( 0.5*( cg1(i,j) + cg1(i+1,j) ) )**2 / (gv%H_to_Z*h_harm)
991 endif ;
enddo ;
enddo 995 if (g%mask2dCu(i,j)>0.)
then 996 sfn_unlim_u(i,:) = ( 1. + cs%FGNV_scale ) * sfn_unlim_u(i,:)
997 call streamfn_solver(nz, c2_h_u(i,:), hn2_u(i,:), sfn_unlim_u(i,:))
999 sfn_unlim_u(i,:) = 0.
1006 if (k > nk_linear)
then 1009 if (uhtot(i,j) <= 0.0)
then 1011 sfn_safe = uhtot(i,j) * (1.0 - h_frac(i,j,k)) * gv%H_to_Z
1013 sfn_safe = uhtot(i,j) * (1.0 - h_frac(i+1,j,k)) * gv%H_to_Z
1017 sfn_est = (sfn_unlim_u(i,k) + slope2_ratio_u(i,k)*sfn_safe) / (1.0 + slope2_ratio_u(i,k))
1019 sfn_est = sfn_unlim_u(i,k)
1024 sfn_in_h = min(max(sfn_est * gv%Z_to_H, -h_avail_rsum(i,j,k)), h_avail_rsum(i+1,j,k))
1028 uhd(i,j,k) = max(min((sfn_in_h - uhtot(i,j)), h_avail(i,j,k)), &
1031 if (cs%id_sfn_x>0) diag_sfn_x(i,j,k) = diag_sfn_x(i,j,k+1) + uhd(i,j,k)
1043 if (uhtot(i,j) <= 0.0)
then 1044 uhd(i,j,k) = -uhtot(i,j) * h_frac(i,j,k)
1046 uhd(i,j,k) = -uhtot(i,j) * h_frac(i+1,j,k)
1049 if (cs%id_sfn_x>0) diag_sfn_x(i,j,k) = diag_sfn_x(i,j,k+1) + uhd(i,j,k)
1057 uhtot(i,j) = uhtot(i,j) + uhd(i,j,k)
1066 work_u(i,j) = work_u(i,j) + g_scale * &
1067 ( uhtot(i,j) * drdkde_u(i,k) - &
1068 (uhd(i,j,k) * drdi_u(i,k)) * 0.25 * &
1069 ((e(i,j,k) + e(i,j,k+1)) + (e(i+1,j,k) + e(i+1,j,k+1))) )
1077 eosdom_v(:) = eos_domain(g%HI)
1095 if (find_work .and. .not.(use_eos))
then 1096 drdja = 0.0 ; drdjb = 0.0
1097 drdkl = gv%Rlay(k) - gv%Rlay(k-1) ; drdkr = drdkl
1100 calc_derivatives = use_eos .and. (k >= nk_linear) .and. &
1101 (find_work .or. .not. present_slope_y .or. cs%use_FGNV_streamfn .or. use_stanley)
1103 if (calc_derivatives)
then 1105 pres_v(i) = 0.5*(pres(i,j,k) + pres(i,j+1,k))
1106 t_v(i) = 0.25*((t(i,j,k) + t(i,j+1,k)) + (t(i,j,k-1) + t(i,j+1,k-1)))
1107 s_v(i) = 0.25*((s(i,j,k) + s(i,j+1,k)) + (s(i,j,k-1) + s(i,j+1,k-1)))
1109 call calculate_density_derivs(t_v, s_v, pres_v, drho_dt_v, drho_ds_v, &
1110 tv%eqn_of_state, eosdom_v)
1112 if (use_stanley)
then 1115 call calculate_density_second_derivs(t_v, s_v, pres_v, &
1116 scrap, scrap, drho_dt_dt_v, scrap, scrap, &
1117 is, ie-is+1, tv%eqn_of_state)
1120 if (calc_derivatives)
then 1122 drdja = drho_dt_v(i) * (t(i,j+1,k-1)-t(i,j,k-1)) + &
1123 drho_ds_v(i) * (s(i,j+1,k-1)-s(i,j,k-1))
1124 drdjb = drho_dt_v(i) * (t(i,j+1,k)-t(i,j,k)) + &
1125 drho_ds_v(i) * (s(i,j+1,k)-s(i,j,k))
1128 drdkl = (drho_dt_v(i) * (t(i,j,k)-t(i,j,k-1)) + &
1129 drho_ds_v(i) * (s(i,j,k)-s(i,j,k-1)))
1130 drdkr = (drho_dt_v(i) * (t(i,j+1,k)-t(i,j+1,k-1)) + &
1131 drho_ds_v(i) * (s(i,j+1,k)-s(i,j+1,k-1)))
1132 drdkde_v(i,k) = drdkr * e(i,j+1,k) - drdkl * e(i,j,k)
1133 elseif (find_work)
then 1134 drdkde_v(i,k) = drdkr * e(i,j+1,k) - drdkl * e(i,j,k)
1136 if (use_stanley)
then 1139 drdja = drdja + drho_dt_dt_v(i) * 0.5 * ( tsgs2(i,j+1,k-1)-tsgs2(i,j,k-1) )
1140 drdjb = drdjb + drho_dt_dt_v(i) * 0.5 * ( tsgs2(i,j+1,k)-tsgs2(i,j,k) )
1143 if (find_work) drdj_v(i,k) = drdjb
1145 if (k > nk_linear)
then 1147 if (cs%use_FGNV_streamfn .or. find_work .or. .not. present_slope_y)
then 1148 hg2l = h(i,j,k-1)*h(i,j,k) + h_neglect2
1149 hg2r = h(i,j+1,k-1)*h(i,j+1,k) + h_neglect2
1150 hal = 0.5*(h(i,j,k-1) + h(i,j,k)) + h_neglect
1151 har = 0.5*(h(i,j+1,k-1) + h(i,j+1,k)) + h_neglect
1152 if (gv%Boussinesq)
then 1153 dzal = hal * gv%H_to_Z ; dzar = har * gv%H_to_Z
1155 dzal = 0.5*(e(i,j,k-1) - e(i,j,k+1)) + dz_neglect
1156 dzar = 0.5*(e(i,j+1,k-1) - e(i,j+1,k+1)) + dz_neglect
1160 wtl = hg2l*(har*dzar) ; wtr = hg2r*(hal*dzal)
1162 drdz = (wtl * drdkl + wtr * drdkr) / (dzal*wtl + dzar*wtr)
1166 hg2a = h(i,j,k-1)*h(i,j+1,k-1) + h_neglect2
1167 hg2b = h(i,j,k)*h(i,j+1,k) + h_neglect2
1168 haa = 0.5*(h(i,j,k-1) + h(i,j+1,k-1)) + h_neglect
1169 hab = 0.5*(h(i,j,k) + h(i,j+1,k)) + h_neglect
1172 hn2_v(i,k) = (0.5 * gv%H_to_Z * ( hg2a / haa + hg2b / hab )) * &
1173 max(drdz*g_rho0, n2_floor)
1175 if (present_slope_y)
then 1176 slope = slope_y(i,j,k)
1177 slope2_ratio_v(i,k) = slope**2 * i_slope_max2
1181 wta = hg2a*hab ; wtb = hg2b*haa
1183 drdy = ((wta * drdja + wtb * drdjb) / (wta + wtb) - &
1184 drdz * (e(i,j,k)-e(i,j+1,k))) * g%IdyCv(i,j)
1188 mag_grad2 = drdy**2 + (us%L_to_Z*drdz)**2
1189 if (mag_grad2 > 0.0)
then 1190 slope = drdy / sqrt(mag_grad2)
1191 slope2_ratio_v(i,k) = slope**2 * i_slope_max2
1194 slope2_ratio_v(i,k) = 1.0e20
1200 if (present_int_slope_v)
then 1201 slope = (1.0 - int_slope_v(i,j,k)) * slope + &
1202 int_slope_v(i,j,k) * us%Z_to_L*((e(i,j+1,k)-e(i,j,k)) * g%IdyCv(i,j))
1203 slope2_ratio_v(i,k) = (1.0 - int_slope_v(i,j,k)) * slope2_ratio_v(i,k)
1206 slope_y_pe(i,j,k) = min(slope,cs%slope_max)
1207 hn2_y_pe(i,j,k) = hn2_v(i,k)
1208 if (cs%id_slope_y > 0) cs%diagSlopeY(i,j,k) = slope
1211 sfn_unlim_v(i,k) = -((kh_v(i,j,k)*g%dx_Cv(i,j))*us%L_to_Z*slope)
1215 if (sfn_unlim_v(i,k) > 0.0)
then 1216 if (e(i,j,k) < e(i,j+1,nz+1))
then 1217 sfn_unlim_v(i,k) = 0.0
1219 elseif (e(i,j+1,nz+1) > e(i,j,k+1))
then 1222 sfn_unlim_v(i,k) = sfn_unlim_v(i,k) * ((e(i,j,k) - e(i,j+1,nz+1)) / &
1223 ((e(i,j,k) - e(i,j,k+1)) + dz_neglect))
1226 if (e(i,j+1,k) < e(i,j,nz+1))
then ; sfn_unlim_v(i,k) = 0.0
1227 elseif (e(i,j,nz+1) > e(i,j+1,k+1))
then 1228 sfn_unlim_v(i,k) = sfn_unlim_v(i,k) * ((e(i,j+1,k) - e(i,j,nz+1)) / &
1229 ((e(i,j+1,k) - e(i,j+1,k+1)) + dz_neglect))
1234 if (present_slope_y)
then 1235 slope = slope_y(i,j,k)
1237 slope = us%Z_to_L*((e(i,j,k)-e(i,j+1,k))*g%IdyCv(i,j)) * g%mask2dCv(i,j)
1239 if (cs%id_slope_y > 0) cs%diagSlopeY(i,j,k) = slope
1240 sfn_unlim_v(i,k) = ((kh_v(i,j,k)*g%dx_Cv(i,j))*us%L_to_Z*slope)
1241 hn2_v(i,k) = gv%g_prime(k)
1244 hn2_v(i,k) = n2_floor * dz_neglect
1245 sfn_unlim_v(i,k) = 0.
1247 if (cs%id_sfn_unlim_y>0) diag_sfn_unlim_y(i,j,k) = sfn_unlim_v(i,k)
1251 if (cs%use_FGNV_streamfn)
then 1252 do k=1,nz ;
do i=is,ie ;
if (g%mask2dCv(i,j)>0.)
then 1253 h_harm = max( h_neglect, &
1254 2. * h(i,j,k) * h(i,j+1,k) / ( ( h(i,j,k) + h(i,j+1,k) ) + h_neglect ) )
1255 c2_h_v(i,k) = cs%FGNV_scale * &
1256 ( 0.5*( cg1(i,j) + cg1(i,j+1) ) )**2 / (gv%H_to_Z*h_harm)
1257 endif ;
enddo ;
enddo 1261 if (g%mask2dCv(i,j)>0.)
then 1262 sfn_unlim_v(i,:) = ( 1. + cs%FGNV_scale ) * sfn_unlim_v(i,:)
1263 call streamfn_solver(nz, c2_h_v(i,:), hn2_v(i,:), sfn_unlim_v(i,:))
1265 sfn_unlim_v(i,:) = 0.
1272 if (k > nk_linear)
then 1275 if (vhtot(i,j) <= 0.0)
then 1277 sfn_safe = vhtot(i,j) * (1.0 - h_frac(i,j,k)) * gv%H_to_Z
1279 sfn_safe = vhtot(i,j) * (1.0 - h_frac(i,j+1,k)) * gv%H_to_Z
1283 sfn_est = (sfn_unlim_v(i,k) + slope2_ratio_v(i,k)*sfn_safe) / (1.0 + slope2_ratio_v(i,k))
1285 sfn_est = sfn_unlim_v(i,k)
1290 sfn_in_h = min(max(sfn_est * gv%Z_to_H, -h_avail_rsum(i,j,k)), h_avail_rsum(i,j+1,k))
1294 vhd(i,j,k) = max(min((sfn_in_h - vhtot(i,j)), h_avail(i,j,k)), -h_avail(i,j+1,k))
1296 if (cs%id_sfn_y>0) diag_sfn_y(i,j,k) = diag_sfn_y(i,j,k+1) + vhd(i,j,k)
1308 if (vhtot(i,j) <= 0.0)
then 1309 vhd(i,j,k) = -vhtot(i,j) * h_frac(i,j,k)
1311 vhd(i,j,k) = -vhtot(i,j) * h_frac(i,j+1,k)
1314 if (cs%id_sfn_y>0) diag_sfn_y(i,j,k) = diag_sfn_y(i,j,k+1) + vhd(i,j,k)
1322 vhtot(i,j) = vhtot(i,j) + vhd(i,j,k)
1331 work_v(i,j) = work_v(i,j) + g_scale * &
1332 ( vhtot(i,j) * drdkde_v(i,k) - &
1333 (vhd(i,j,k) * drdj_v(i,k)) * 0.25 * &
1334 ((e(i,j,k) + e(i,j,k+1)) + (e(i,j+1,k) + e(i,j+1,k+1))) )
1342 if (.not.find_work .or. .not.(use_eos))
then 1343 do j=js,je ;
do i=is-1,ie ; uhd(i,j,1) = -uhtot(i,j) ;
enddo ;
enddo 1344 do j=js-1,je ;
do i=is,ie ; vhd(i,j,1) = -vhtot(i,j) ;
enddo ;
enddo 1346 eosdom_u(1) = (is-1) - (g%IsdB-1) ; eosdom_u(2) = ie - (g%IsdB-1)
1351 pres_u(i) = 0.5*(pres(i,j,1) + pres(i+1,j,1))
1352 t_u(i) = 0.5*(t(i,j,1) + t(i+1,j,1))
1353 s_u(i) = 0.5*(s(i,j,1) + s(i+1,j,1))
1355 call calculate_density_derivs(t_u, s_u, pres_u, drho_dt_u, drho_ds_u, &
1356 tv%eqn_of_state, eosdom_u )
1359 uhd(i,j,1) = -uhtot(i,j)
1362 drdib = drho_dt_u(i) * (t(i+1,j,1)-t(i,j,1)) + &
1363 drho_ds_u(i) * (s(i+1,j,1)-s(i,j,1))
1365 if (cs%use_GM_work_bug)
then 1366 work_u(i,j) = work_u(i,j) + g_scale * &
1367 ( (uhd(i,j,1) * drdib) * 0.25 * &
1368 ((e(i,j,1) + e(i,j,2)) + (e(i+1,j,1) + e(i+1,j,2))) )
1370 work_u(i,j) = work_u(i,j) - g_scale * &
1371 ( (uhd(i,j,1) * drdib) * 0.25 * &
1372 ((e(i,j,1) + e(i,j,2)) + (e(i+1,j,1) + e(i+1,j,2))) )
1377 eosdom_v(:) = eos_domain(g%HI)
1382 pres_v(i) = 0.5*(pres(i,j,1) + pres(i,j+1,1))
1383 t_v(i) = 0.5*(t(i,j,1) + t(i,j+1,1))
1384 s_v(i) = 0.5*(s(i,j,1) + s(i,j+1,1))
1386 call calculate_density_derivs(t_v, s_v, pres_v, drho_dt_v, drho_ds_v, &
1387 tv%eqn_of_state, eosdom_v)
1390 vhd(i,j,1) = -vhtot(i,j)
1393 drdjb = drho_dt_v(i) * (t(i,j+1,1)-t(i,j,1)) + &
1394 drho_ds_v(i) * (s(i,j+1,1)-s(i,j,1))
1396 work_v(i,j) = work_v(i,j) - g_scale * &
1397 ( (vhd(i,j,1) * drdjb) * 0.25 * &
1398 ((e(i,j,1) + e(i,j,2)) + (e(i,j+1,1) + e(i,j+1,2))) )
1403 if (find_work)
then ;
do j=js,je ;
do i=is,ie
1405 work_h = 0.5 * g%IareaT(i,j) * &
1406 ((work_u(i-1,j) + work_u(i,j)) + (work_v(i,j-1) + work_v(i,j)))
1407 if (
associated(cs%GMwork)) cs%GMwork(i,j) = work_h
1408 if (
associated(meke) .and. .not.cs%GM_src_alt)
then ;
if (
associated(meke%GM_src))
then 1409 meke%GM_src(i,j) = meke%GM_src(i,j) + work_h
1411 enddo ;
enddo ;
endif 1413 if (find_work .and. cs%GM_src_alt .and.
associated(meke))
then ;
if (
associated(meke%GM_src))
then 1414 do j=js,je ;
do i=is,ie ;
do k=nz,1,-1
1415 pe_release_h = -0.25*(kh_u(i,j,k)*(slope_x_pe(i,j,k)**2) * hn2_x_pe(i,j,k) + &
1416 kh_u(i-1,j,k)*(slope_x_pe(i-1,j,k)**2) * hn2_x_pe(i-1,j,k) + &
1417 kh_v(i,j,k)*(slope_y_pe(i,j,k)**2) * hn2_y_pe(i,j,k) + &
1418 kh_v(i,j-1,k)*(slope_y_pe(i,j-1,k)**2) * hn2_y_pe(i,j-1,k))
1419 meke%GM_src(i,j) = meke%GM_src(i,j) + us%L_to_Z**2 * gv%Rho0 * pe_release_h
1420 enddo ;
enddo ;
enddo 1423 if (cs%id_slope_x > 0)
call post_data(cs%id_slope_x, cs%diagSlopeX, cs%diag)
1424 if (cs%id_slope_y > 0)
call post_data(cs%id_slope_y, cs%diagSlopeY, cs%diag)
1425 if (cs%id_sfn_x > 0)
call post_data(cs%id_sfn_x, diag_sfn_x, cs%diag)
1426 if (cs%id_sfn_y > 0)
call post_data(cs%id_sfn_y, diag_sfn_y, cs%diag)
1427 if (cs%id_sfn_unlim_x > 0)
call post_data(cs%id_sfn_unlim_x, diag_sfn_unlim_x, cs%diag)
1428 if (cs%id_sfn_unlim_y > 0)
call post_data(cs%id_sfn_unlim_y, diag_sfn_unlim_y, cs%diag)
1430 end subroutine thickness_diffuse_full
1433 subroutine streamfn_solver(nk, c2_h, hN2, sfn)
1434 integer,
intent(in) :: nk
1435 real,
dimension(nk),
intent(in) :: c2_h
1436 real,
dimension(nk+1),
intent(in) :: hN2
1437 real,
dimension(nk+1),
intent(inout) :: sfn
1443 real :: b_denom, beta, d1, c1(nk)
1446 b_denom = hn2(2) + c2_h(1)
1447 beta = 1.0 / ( b_denom + c2_h(2) )
1449 sfn(2) = ( beta * hn2(2) )*sfn(2)
1451 c1(k-1) = beta * c2_h(k-1)
1452 b_denom = hn2(k) + d1*c2_h(k-1)
1453 beta = 1.0 / (b_denom + c2_h(k))
1455 sfn(k) = beta * (hn2(k)*sfn(k) + c2_h(k-1)*sfn(k-1))
1457 c1(nk) = beta * c2_h(nk)
1460 sfn(k) = sfn(k) + c1(k)*sfn(k+1)
1463 end subroutine streamfn_solver
1466 subroutine add_detangling_kh(h, e, Kh_u, Kh_v, KH_u_CFL, KH_v_CFL, tv, dt, G, GV, US, CS, &
1467 int_slope_u, int_slope_v)
1468 type(ocean_grid_type),
intent(in) :: G
1469 type(verticalgrid_type),
intent(in) :: GV
1470 type(unit_scale_type),
intent(in) :: US
1471 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
1472 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1),
intent(in) :: e
1473 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)+1),
intent(inout) :: Kh_u
1475 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)+1),
intent(inout) :: Kh_v
1477 real,
dimension(SZIB_(G),SZJ_(G)),
intent(in) :: Kh_u_CFL
1479 real,
dimension(SZI_(G),SZJB_(G)),
intent(in) :: Kh_v_CFL
1481 type(thermo_var_ptrs),
intent(in) :: tv
1482 real,
intent(in) :: dt
1484 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)+1),
intent(inout) :: int_slope_u
1488 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)+1),
intent(inout) :: int_slope_v
1493 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
1496 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)) :: &
1499 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)) :: &
1502 real,
dimension(SZI_(G),SZJ_(G)) :: &
1534 real :: denom, I_denom
1542 real,
dimension(SZIB_(G),SZK_(G)+1) :: &
1565 real,
dimension(SZIB_(G)) :: &
1567 logical,
dimension(SZIB_(G)) :: &
1569 integer :: i, j, k, n, ish, jsh, is, ie, js, je, nz, k_top
1570 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1572 k_top = gv%nk_rho_varies + 1
1573 h_neglect = gv%H_subroundoff
1578 if (cs%detangle_time > dt) kh_scale = 0.5 * dt / cs%detangle_time
1580 do j=js-1,je+1 ;
do i=is-1,ie+1
1581 de_top(i,j,k_top) = 0.0 ; de_bot(i,j) = 0.0
1583 do k=k_top+1,nz ;
do j=js-1,je+1 ;
do i=is-1,ie+1
1584 de_top(i,j,k) = de_top(i,j,k-1) + h(i,j,k-1)
1585 enddo ;
enddo ;
enddo 1587 do j=js,je ;
do i=is-1,ie
1588 kh_lay_u(i,j,nz) = 0.0 ; kh_lay_u(i,j,k_top) = 0.0
1590 do j=js-1,je ;
do i=is,ie
1591 kh_lay_v(i,j,nz) = 0.0 ; kh_lay_v(i,j,k_top) = 0.0
1594 do k=nz-1,k_top+1,-1
1596 do j=js-1,je+1 ;
do i=is-1,ie+1
1597 de_bot(i,j) = de_bot(i,j) + h(i,j,k+1)
1600 do j=js,je ;
do i=is-1,ie ;
if (g%mask2dCu(i,j) > 0.0)
then 1601 if (h(i,j,k) > h(i+1,j,k))
then 1603 h1 = max( h(i+1,j,k), h2 - min(de_bot(i+1,j), de_top(i+1,j,k)) )
1606 h1 = max( h(i,j,k), h2 - min(de_bot(i,j), de_top(i,j,k)) )
1608 jag_rat = (h2 - h1)**2 / (h2 + h1 + h_neglect)**2
1609 kh_lay_u(i,j,k) = (kh_scale * kh_u_cfl(i,j)) * jag_rat**2
1610 endif ;
enddo ;
enddo 1612 do j=js-1,je ;
do i=is,ie ;
if (g%mask2dCv(i,j) > 0.0)
then 1613 if (h(i,j,k) > h(i,j+1,k))
then 1615 h1 = max( h(i,j+1,k), h2 - min(de_bot(i,j+1), de_top(i,j+1,k)) )
1618 h1 = max( h(i,j,k), h2 - min(de_bot(i,j), de_top(i,j,k)) )
1620 jag_rat = (h2 - h1)**2 / (h2 + h1 + h_neglect)**2
1621 kh_lay_v(i,j,k) = (kh_scale * kh_v_cfl(i,j)) * jag_rat**2
1622 endif ;
enddo ;
enddo 1627 i_4t = kh_scale / (4.0 * dt)
1630 if (n==1)
then ; jsh = js ; ish = is-1
1631 else ; jsh = js-1 ; ish = is ;
endif 1638 do_i(i) = (g%mask2dCu(i,j) > 0.0)
1639 kh_max_max(i) = kh_u_cfl(i,j)
1641 do k=1,nz+1 ;
do i=ish,ie
1642 kh_bg(i,k) = kh_u(i,j,k) ; kh(i,k) = kh_bg(i,k)
1643 kh_min_max_p(i,k) = kh_bg(i,k) ; kh_min_max_m(i,k) = kh_bg(i,k)
1644 kh_detangle(i,k) = 0.0
1648 do_i(i) = (g%mask2dCv(i,j) > 0.0) ; kh_max_max(i) = kh_v_cfl(i,j)
1650 do k=1,nz+1 ;
do i=ish,ie
1651 kh_bg(i,k) = kh_v(i,j,k) ; kh(i,k) = kh_bg(i,k)
1652 kh_min_max_p(i,k) = kh_bg(i,k) ; kh_min_max_m(i,k) = kh_bg(i,k)
1653 kh_detangle(i,k) = 0.0
1658 do k=k_top,nz ;
do i=ish,ie ;
if (do_i(i))
then 1661 denom = ((g%IareaT(i+1,j) + g%IareaT(i,j)) * g%dy_Cu(i,j))
1665 dh = i_4t * ((e(i+1,j,k) - e(i+1,j,k+1)) - &
1666 (e(i,j,k) - e(i,j,k+1))) / denom
1670 sign = 1.0 ;
if (dh < 0) sign = -1.0
1671 sl_k = sign * (e(i+1,j,k)-e(i,j,k)) * g%IdxCu(i,j)
1672 sl_kp1 = sign * (e(i+1,j,k+1)-e(i,j,k+1)) * g%IdxCu(i,j)
1677 denom = (sl_k**2 + sl_kp1**2)
1678 wt1 = 0.5 ; wt2 = 0.5
1679 if (denom > 0.0)
then 1680 wt1 = sl_k**2 / denom ; wt2 = sl_kp1**2 / denom
1682 kh_detangle(i,k) = kh_detangle(i,k) + wt1*kh_lay_u(i,j,k)
1683 kh_detangle(i,k+1) = kh_detangle(i,k+1) + wt2*kh_lay_u(i,j,k)
1686 denom = ((g%IareaT(i,j+1) + g%IareaT(i,j)) * g%dx_Cv(i,j))
1688 dh = i_4t * ((e(i,j+1,k) - e(i,j+1,k+1)) - &
1689 (e(i,j,k) - e(i,j,k+1))) / denom
1693 sign = 1.0 ;
if (dh < 0) sign = -1.0
1694 sl_k = sign * (e(i,j+1,k)-e(i,j,k)) * g%IdyCv(i,j)
1695 sl_kp1 = sign * (e(i,j+1,k+1)-e(i,j,k+1)) * g%IdyCv(i,j)
1700 denom = (sl_k**2 + sl_kp1**2)
1701 wt1 = 0.5 ; wt2 = 0.5
1702 if (denom > 0.0)
then 1703 wt1 = sl_k**2 / denom ; wt2 = sl_kp1**2 / denom
1705 kh_detangle(i,k) = kh_detangle(i,k) + wt1*kh_lay_v(i,j,k)
1706 kh_detangle(i,k+1) = kh_detangle(i,k+1) + wt2*kh_lay_v(i,j,k)
1709 if (adh == 0.0)
then 1710 kh_min_m(i,k+1) = 1.0 ; kh0_min_m(i,k+1) = 0.0
1711 kh_max_m(i,k+1) = 1.0 ; kh0_max_m(i,k+1) = 0.0
1712 kh_min_p(i,k) = 1.0 ; kh0_min_p(i,k) = 0.0
1713 kh_max_p(i,k) = 1.0 ; kh0_max_p(i,k) = 0.0
1714 elseif (adh > 0.0)
then 1715 if (sl_k <= sl_kp1)
then 1718 kh_min_m(i,k+1) = 1.0 ; kh0_min_m(i,k+1) = 0.0
1719 kh_max_m(i,k+1) = 1.0 ; kh0_max_m(i,k+1) = 0.0
1720 kh_min_p(i,k) = 1.0 ; kh0_min_p(i,k) = 0.0
1721 kh_max_p(i,k) = 1.0 ; kh0_max_p(i,k) = 0.0
1722 elseif (sl_k <= 0.0)
then 1723 i_sl = -1.0 / sl_kp1
1725 irsl = 1e9 ;
if (rsl > 1e-9) irsl = 1.0/rsl
1728 if (kh_max_max(i) > 0) &
1729 fn_r = min(sqrt(rsl), rsl + (adh * i_sl) / (kh_max_max(i)))
1731 kh_min_m(i,k+1) = fn_r ; kh0_min_m(i,k+1) = 0.0
1732 kh_max_m(i,k+1) = rsl ; kh0_max_m(i,k+1) = adh * i_sl
1733 kh_min_p(i,k) = irsl ; kh0_min_p(i,k) = -adh * (i_sl*irsl)
1734 kh_max_p(i,k) = 1.0/(fn_r + 1.0e-30) ; kh0_max_p(i,k) = 0.0
1735 elseif (sl_kp1 < 0.0)
then 1736 i_sl_k = 1e18*us%Z_to_L ;
if (sl_k > 1e-18*us%L_to_Z) i_sl_k = 1.0 / sl_k
1737 i_sl_kp1 = 1e18*us%Z_to_L ;
if (-sl_kp1 > 1e-18*us%L_to_Z) i_sl_kp1 = -1.0 / sl_kp1
1739 kh_min_m(i,k+1) = 0.0 ; kh0_min_m(i,k+1) = 0.0
1740 kh_max_m(i,k+1) = - sl_k*i_sl_kp1 ; kh0_max_m(i,k+1) = adh*i_sl_kp1
1741 kh_min_p(i,k) = 0.0 ; kh0_min_p(i,k) = 0.0
1742 kh_max_p(i,k) = sl_kp1*i_sl_k ; kh0_max_p(i,k) = adh*i_sl_k
1746 kh_max = adh / (sl_k - sl_kp1)
1747 kh_min_max_p(i,k) = max(kh_min_max_p(i,k), kh_max)
1748 kh_min_max_m(i,k+1) = max(kh_min_max_m(i,k+1), kh_max)
1752 irsl = 1e9 ;
if (rsl > 1e-9) irsl = 1.0/rsl
1756 if (kh_max_max(i) > 0) &
1757 fn_r = min(sqrt(rsl), rsl + (adh * i_sl) / kh_max_max(i))
1759 kh_min_m(i,k+1) = irsl ; kh0_min_m(i,k+1) = -adh * (i_sl*irsl)
1760 kh_max_m(i,k+1) = 1.0/(fn_r + 1.0e-30) ; kh0_max_m(i,k+1) = 0.0
1761 kh_min_p(i,k) = fn_r ; kh0_min_p(i,k) = 0.0
1762 kh_max_p(i,k) = rsl ; kh0_max_p(i,k) = adh * i_sl
1765 endif ;
enddo ;
enddo 1767 do k=k_top,nz+1,nz+1-k_top ;
do i=ish,ie ;
if (do_i(i))
then 1769 kh_min_m(i,k) = 0.0 ; kh0_min_m(i,k) = 0.0
1770 kh_max_m(i,k) = 0.0 ; kh0_max_m(i,k) = 0.0
1771 kh_min_p(i,k) = 0.0 ; kh0_min_p(i,k) = 0.0
1772 kh_max_p(i,k) = 0.0 ; kh0_max_p(i,k) = 0.0
1773 kh_min_max_p(i,k) = kh_bg(i,k)
1774 kh_min_max_m(i,k) = kh_bg(i,k)
1775 endif ;
enddo ;
enddo 1785 do k=k_top+1,nz ;
do i=ish,ie ;
if (do_i(i))
then 1786 kh(i,k) = max(kh_bg(i,k), kh_detangle(i,k), &
1787 min(kh_min_m(i,k)*kh(i,k-1) + kh0_min_m(i,k), kh(i,k-1)))
1789 if (kh0_max_m(i,k) > kh_bg(i,k)) kh(i,k) = min(kh(i,k), kh0_max_m(i,k))
1790 if (kh0_max_p(i,k) > kh_bg(i,k)) kh(i,k) = min(kh(i,k), kh0_max_p(i,k))
1791 endif ;
enddo ;
enddo 1793 do k=nz,k_top+1,-1 ;
do i=ish,ie ;
if (do_i(i))
then 1794 kh(i,k) = max(kh(i,k), min(kh_min_p(i,k)*kh(i,k+1) + kh0_min_p(i,k), kh(i,k+1)))
1796 kh_max = max(kh_min_max_p(i,k), kh_max_p(i,k)*kh(i,k+1) + kh0_max_p(i,k))
1797 kh(i,k) = min(kh(i,k), kh_max)
1798 endif ;
enddo ;
enddo 1803 do k=k_top+1,nz ;
do i=ish,ie ;
if (do_i(i))
then 1804 kh_max = max(kh_min_max_m(i,k), kh_max_m(i,k)*kh(i,k-1) + kh0_max_m(i,k))
1805 if (kh(i,k) > kh_max) kh(i,k) = kh_max
1806 endif ;
enddo ;
enddo 1858 do k=k_top+1,nz ;
do i=ish,ie
1859 if (kh(i,k) > kh_u(i,j,k))
then 1860 dkh = (kh(i,k) - kh_u(i,j,k))
1861 int_slope_u(i,j,k) = dkh / kh(i,k)
1862 kh_u(i,j,k) = kh(i,k)
1866 do k=k_top+1,nz ;
do i=ish,ie
1867 if (kh(i,k) > kh_v(i,j,k))
then 1868 dkh = kh(i,k) - kh_v(i,j,k)
1869 int_slope_v(i,j,k) = dkh / kh(i,k)
1870 kh_v(i,j,k) = kh(i,k)
1878 end subroutine add_detangling_kh
1881 subroutine thickness_diffuse_init(Time, G, GV, US, param_file, diag, CDp, CS)
1882 type(time_type),
intent(in) :: Time
1883 type(ocean_grid_type),
intent(in) :: G
1884 type(verticalgrid_type),
intent(in) :: GV
1885 type(unit_scale_type),
intent(in) :: US
1886 type(param_file_type),
intent(in) :: param_file
1887 type(diag_ctrl),
target,
intent(inout) :: diag
1888 type(cont_diag_ptrs),
intent(inout) :: CDp
1892 #include "version_variable.h" 1893 character(len=40) :: mdl =
"MOM_thickness_diffuse" 1898 logical :: default_2018_answers
1900 if (
associated(cs))
then 1901 call mom_error(warning, &
1902 "Thickness_diffuse_init called with an associated control structure.")
1904 else ;
allocate(cs) ;
endif 1909 call log_version(param_file, mdl, version,
"")
1910 call get_param(param_file, mdl,
"THICKNESSDIFFUSE", cs%thickness_diffuse, &
1911 "If true, interface heights are diffused with a "//&
1912 "coefficient of KHTH.", default=.false.)
1913 call get_param(param_file, mdl,
"KHTH", cs%Khth, &
1914 "The background horizontal thickness diffusivity.", &
1915 default=0.0, units=
"m2 s-1", scale=us%m_to_L**2*us%T_to_s)
1916 call get_param(param_file, mdl,
"KHTH_SLOPE_CFF", cs%KHTH_Slope_Cff, &
1917 "The nondimensional coefficient in the Visbeck formula "//&
1918 "for the interface depth diffusivity", units=
"nondim", &
1920 call get_param(param_file, mdl,
"KHTH_MIN", cs%KHTH_Min, &
1921 "The minimum horizontal thickness diffusivity.", &
1922 default=0.0, units=
"m2 s-1", scale=us%m_to_L**2*us%T_to_s)
1923 call get_param(param_file, mdl,
"KHTH_MAX", cs%KHTH_Max, &
1924 "The maximum horizontal thickness diffusivity.", &
1925 default=0.0, units=
"m2 s-1", scale=us%m_to_L**2*us%T_to_s)
1926 call get_param(param_file, mdl,
"KHTH_MAX_CFL", cs%max_Khth_CFL, &
1927 "The maximum value of the local diffusive CFL ratio that "//&
1928 "is permitted for the thickness diffusivity. 1.0 is the "//&
1929 "marginally unstable value in a pure layered model, but "//&
1930 "much smaller numbers (e.g. 0.1) seem to work better for "//&
1931 "ALE-based models.", units =
"nondimensional", default=0.8)
1937 if (cs%max_Khth_CFL < 0.0) cs%max_Khth_CFL = 0.0
1938 call get_param(param_file, mdl,
"DETANGLE_INTERFACES", cs%detangle_interfaces, &
1939 "If defined add 3-d structured enhanced interface height "//&
1940 "diffusivities to horizontally smooth jagged layers.", &
1942 cs%detangle_time = 0.0
1943 if (cs%detangle_interfaces) &
1944 call get_param(param_file, mdl,
"DETANGLE_TIMESCALE", cs%detangle_time, &
1945 "A timescale over which maximally jagged grid-scale "//&
1946 "thickness variations are suppressed. This must be "//&
1947 "longer than DT, or 0 to use DT.", units=
"s", default=0.0, scale=us%s_to_T)
1948 call get_param(param_file, mdl,
"KHTH_SLOPE_MAX", cs%slope_max, &
1949 "A slope beyond which the calculated isopycnal slope is "//&
1950 "not reliable and is scaled away.", units=
"nondim", default=0.01)
1951 call get_param(param_file, mdl,
"KD_SMOOTH", cs%kappa_smooth, &
1952 "A diapycnal diffusivity that is used to interpolate "//&
1953 "more sensible values of T & S into thin layers.", &
1954 units=
"m2 s-1", default=1.0e-6, scale=us%m_to_Z**2*us%T_to_s)
1955 call get_param(param_file, mdl,
"KHTH_USE_FGNV_STREAMFUNCTION", cs%use_FGNV_streamfn, &
1956 "If true, use the streamfunction formulation of "//&
1957 "Ferrari et al., 2010, which effectively emphasizes "//&
1958 "graver vertical modes by smoothing in the vertical.", &
1960 call get_param(param_file, mdl,
"FGNV_FILTER_SCALE", cs%FGNV_scale, &
1961 "A coefficient scaling the vertical smoothing term in the "//&
1962 "Ferrari et al., 2010, streamfunction formulation.", &
1963 units=
"nondim", default=1., do_not_log=.not.cs%use_FGNV_streamfn)
1964 call get_param(param_file, mdl,
"FGNV_C_MIN", cs%FGNV_c_min, &
1965 "A minium wave speed used in the Ferrari et al., 2010, "//&
1966 "streamfunction formulation.", &
1967 default=0., units=
"m s-1", scale=us%m_s_to_L_T, do_not_log=.not.cs%use_FGNV_streamfn)
1968 call get_param(param_file, mdl,
"FGNV_STRAT_FLOOR", strat_floor, &
1969 "A floor for Brunt-Vasaila frequency in the Ferrari et al., 2010, "//&
1970 "streamfunction formulation, expressed as a fraction of planetary "//&
1971 "rotation, OMEGA. This should be tiny but non-zero to avoid degeneracy.", &
1972 default=1.e-15, units=
"nondim", do_not_log=.not.cs%use_FGNV_streamfn)
1973 call get_param(param_file, mdl,
"STANLEY_PRM_DET_COEFF", cs%Stanley_det_coeff, &
1974 "The coefficient correlating SGS temperature variance with the mean "//&
1975 "temperature gradient in the deterministic part of the Stanley parameterization. "//&
1976 "Negative values disable the scheme.", units=
"nondim", default=-1.0)
1977 call get_param(param_file, mdl,
"OMEGA", omega, &
1978 "The rotation rate of the earth.", &
1979 default=7.2921e-5, units=
"s-1", scale=us%T_to_s, do_not_log=.not.cs%use_FGNV_streamfn)
1980 if (cs%use_FGNV_streamfn) cs%N2_floor = (strat_floor*omega)**2
1981 call get_param(param_file, mdl,
"DEBUG", cs%debug, &
1982 "If true, write out verbose debugging data.", &
1983 default=.false., debuggingparam=.true.)
1985 call get_param(param_file, mdl,
"MEKE_GM_SRC_ALT", cs%GM_src_alt, &
1986 "If true, use the GM energy conversion form S^2*N^2*kappa rather "//&
1987 "than the streamfunction for the GM source term.", default=.false.)
1988 call get_param(param_file, mdl,
"MEKE_GEOMETRIC", cs%MEKE_GEOMETRIC, &
1989 "If true, uses the GM coefficient formulation from the GEOMETRIC "//&
1990 "framework (Marshall et al., 2012).", default=.false.)
1991 if (cs%MEKE_GEOMETRIC)
then 1992 call get_param(param_file, mdl,
"MEKE_GEOMETRIC_EPSILON", cs%MEKE_GEOMETRIC_epsilon, &
1993 "Minimum Eady growth rate used in the calculation of GEOMETRIC "//&
1994 "thickness diffusivity.", units=
"s-1", default=1.0e-7, scale=us%T_to_s)
1995 call get_param(param_file, mdl,
"MEKE_GEOMETRIC_ALPHA", cs%MEKE_GEOMETRIC_alpha, &
1996 "The nondimensional coefficient governing the efficiency of the GEOMETRIC "//&
1997 "thickness diffusion.", units=
"nondim", default=0.05)
1999 call get_param(param_file, mdl,
"DEFAULT_2018_ANSWERS", default_2018_answers, &
2000 "This sets the default value for the various _2018_ANSWERS parameters.", &
2002 call get_param(param_file, mdl,
"MEKE_GEOMETRIC_2018_ANSWERS", cs%MEKE_GEOM_answers_2018, &
2003 "If true, use expressions in the MEKE_GEOMETRIC calculation that recover the "//&
2004 "answers from the original implementation. Otherwise, use expressions that "//&
2005 "satisfy rotational symmetry.", default=default_2018_answers)
2008 call get_param(param_file, mdl,
"USE_KH_IN_MEKE", cs%Use_KH_in_MEKE, &
2009 "If true, uses the thickness diffusivity calculated here to diffuse MEKE.", &
2012 call get_param(param_file, mdl,
"USE_GME", cs%use_GME_thickness_diffuse, &
2013 "If true, use the GM+E backscatter scheme in association "//&
2014 "with the Gent and McWilliams parameterization.", default=.false.)
2016 call get_param(param_file, mdl,
"USE_GM_WORK_BUG", cs%use_GM_work_bug, &
2017 "If true, compute the top-layer work tendency on the u-grid "//&
2018 "with the incorrect sign, for legacy reproducibility.", &
2021 if (cs%use_GME_thickness_diffuse)
then 2022 call safe_alloc_ptr(cs%KH_u_GME,g%IsdB,g%IedB,g%jsd,g%jed,g%ke+1)
2023 call safe_alloc_ptr(cs%KH_v_GME,g%isd,g%ied,g%JsdB,g%JedB,g%ke+1)
2026 cs%id_uhGM = register_diag_field(
'ocean_model',
'uhGM', diag%axesCuL, time, &
2027 'Time Mean Diffusive Zonal Thickness Flux', &
2028 'kg s-1', conversion=gv%H_to_kg_m2*us%L_to_m**2*us%s_to_T, &
2029 y_cell_method=
'sum', v_extensive=.true.)
2030 if (cs%id_uhGM > 0)
call safe_alloc_ptr(cdp%uhGM,g%IsdB,g%IedB,g%jsd,g%jed,g%ke)
2031 cs%id_vhGM = register_diag_field(
'ocean_model',
'vhGM', diag%axesCvL, time, &
2032 'Time Mean Diffusive Meridional Thickness Flux', &
2033 'kg s-1', conversion=gv%H_to_kg_m2*us%L_to_m**2*us%s_to_T, &
2034 x_cell_method=
'sum', v_extensive=.true.)
2035 if (cs%id_vhGM > 0)
call safe_alloc_ptr(cdp%vhGM,g%isd,g%ied,g%JsdB,g%JedB,g%ke)
2037 cs%id_GMwork = register_diag_field(
'ocean_model',
'GMwork', diag%axesT1, time, &
2038 'Integrated Tendency of Ocean Mesoscale Eddy KE from Parameterized Eddy Advection', &
2039 'W m-2', conversion=us%RZ3_T3_to_W_m2*us%L_to_Z**2, cmor_field_name=
'tnkebto', &
2040 cmor_long_name=
'Integrated Tendency of Ocean Mesoscale Eddy KE from Parameterized Eddy Advection', &
2041 cmor_standard_name=
'tendency_of_ocean_eddy_kinetic_energy_content_due_to_parameterized_eddy_advection')
2042 if (cs%id_GMwork > 0)
call safe_alloc_ptr(cs%GMwork,g%isd,g%ied,g%jsd,g%jed)
2044 cs%id_KH_u = register_diag_field(
'ocean_model',
'KHTH_u', diag%axesCui, time, &
2045 'Parameterized mesoscale eddy advection diffusivity at U-point', &
2046 'm2 s-1', conversion=us%L_to_m**2*us%s_to_T)
2047 cs%id_KH_v = register_diag_field(
'ocean_model',
'KHTH_v', diag%axesCvi, time, &
2048 'Parameterized mesoscale eddy advection diffusivity at V-point', &
2049 'm2 s-1', conversion=us%L_to_m**2*us%s_to_T)
2050 cs%id_KH_t = register_diag_field(
'ocean_model',
'KHTH_t', diag%axesTL, time, &
2051 'Ocean Tracer Diffusivity due to Parameterized Mesoscale Advection', &
2052 'm2 s-1', conversion=us%L_to_m**2*us%s_to_T, &
2053 cmor_field_name=
'diftrblo', &
2054 cmor_long_name=
'Ocean Tracer Diffusivity due to Parameterized Mesoscale Advection', &
2055 cmor_units=
'm2 s-1', &
2056 cmor_standard_name=
'ocean_tracer_diffusivity_due_to_parameterized_mesoscale_advection')
2058 cs%id_KH_u1 = register_diag_field(
'ocean_model',
'KHTH_u1', diag%axesCu1, time, &
2059 'Parameterized mesoscale eddy advection diffusivity at U-points (2-D)', &
2060 'm2 s-1', conversion=us%L_to_m**2*us%s_to_T)
2061 cs%id_KH_v1 = register_diag_field(
'ocean_model',
'KHTH_v1', diag%axesCv1, time, &
2062 'Parameterized mesoscale eddy advection diffusivity at V-points (2-D)', &
2063 'm2 s-1', conversion=us%L_to_m**2*us%s_to_T)
2064 cs%id_KH_t1 = register_diag_field(
'ocean_model',
'KHTH_t1', diag%axesT1, time, &
2065 'Parameterized mesoscale eddy advection diffusivity at T-points (2-D)', &
2066 'm2 s-1', conversion=us%L_to_m**2*us%s_to_T)
2068 cs%id_slope_x = register_diag_field(
'ocean_model',
'neutral_slope_x', diag%axesCui, time, &
2069 'Zonal slope of neutral surface',
'nondim')
2070 if (cs%id_slope_x > 0)
call safe_alloc_ptr(cs%diagSlopeX,g%IsdB,g%IedB,g%jsd,g%jed,g%ke+1)
2071 cs%id_slope_y = register_diag_field(
'ocean_model',
'neutral_slope_y', diag%axesCvi, time, &
2072 'Meridional slope of neutral surface',
'nondim')
2073 if (cs%id_slope_y > 0)
call safe_alloc_ptr(cs%diagSlopeY,g%isd,g%ied,g%JsdB,g%JedB,g%ke+1)
2074 cs%id_sfn_x = register_diag_field(
'ocean_model',
'GM_sfn_x', diag%axesCui, time, &
2075 'Parameterized Zonal Overturning Streamfunction', &
2076 'm3 s-1', conversion=gv%H_to_m*us%L_to_m**2*us%s_to_T)
2077 cs%id_sfn_y = register_diag_field(
'ocean_model',
'GM_sfn_y', diag%axesCvi, time, &
2078 'Parameterized Meridional Overturning Streamfunction', &
2079 'm3 s-1', conversion=gv%H_to_m*us%L_to_m**2*us%s_to_T)
2080 cs%id_sfn_unlim_x = register_diag_field(
'ocean_model',
'GM_sfn_unlim_x', diag%axesCui, time, &
2081 'Parameterized Zonal Overturning Streamfunction before limiting/smoothing', &
2082 'm3 s-1', conversion=us%Z_to_m*us%L_to_m**2*us%s_to_T)
2083 cs%id_sfn_unlim_y = register_diag_field(
'ocean_model',
'GM_sfn_unlim_y', diag%axesCvi, time, &
2084 'Parameterized Meridional Overturning Streamfunction before limiting/smoothing', &
2085 'm3 s-1', conversion=us%Z_to_m*us%L_to_m**2*us%s_to_T)
2087 end subroutine thickness_diffuse_init
2090 subroutine thickness_diffuse_get_kh(CS, KH_u_GME, KH_v_GME, G)
2093 type(ocean_grid_type),
intent(in) :: G
2094 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)+1),
intent(inout) :: KH_u_GME
2096 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)+1),
intent(inout) :: KH_v_GME
2101 do k=1,g%ke+1 ;
do j = g%jsc, g%jec ;
do i = g%isc-1, g%iec
2102 kh_u_gme(i,j,k) = cs%KH_u_GME(i,j,k)
2103 enddo ;
enddo ;
enddo 2105 do k=1,g%ke+1 ;
do j = g%jsc-1, g%jec ;
do i = g%isc, g%iec
2106 kh_v_gme(i,j,k) = cs%KH_v_GME(i,j,k)
2107 enddo ;
enddo ;
enddo 2109 end subroutine thickness_diffuse_get_kh
2112 subroutine thickness_diffuse_end(CS)
2115 if (
associated(cs))
deallocate(cs)
2116 end subroutine thickness_diffuse_end
Calculates the heights of sruface or all interfaces from layer thicknesses.
Functions for calculating interface heights, including free surface height.
Ocean grid type. See mom_grid for details.
Calculates density of sea water from T, S and P.
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
This type is used to exchange information related to the MEKE calculations.
The MOM6 facility to parse input files for runtime parameters.
Variable mixing coefficients.
Do a halo update on a pair of arrays representing the two components of a vector. ...
Variable mixing coefficients.
Make a diagnostic available for averaging or output.
Describes various unit conversion factors.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Describes the decomposed MOM domain and has routines for communications across PEs.
Thickness diffusion (or Gent McWilliams)
Pointers to arrays with transports, which can later be used for derived diagnostics, like energy balances.
Routines for error handling and I/O management.
Calculate the derivatives of density with temperature and salinity from T, S, and P...
Provides subroutines for quantities specific to the equation of state.
An overloaded interface to log version information about modules.
Describes the vertical ocean grid, including unit conversion factors.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Control structure for thickness diffusion.
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.
Calculates the second derivatives of density with various combinations of temperature, salinity, and pressure from T, S and P.
Do a halo update on an array.
Calculations of isoneutral slopes and stratification.
An overloaded interface to read and log the values of various types of parameters.
Provides checksumming functions for debugging.