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)
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
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
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)))
844 tv%eqn_of_state, eosdom_u)
846 if (use_stanley)
then
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)))
1110 tv%eqn_of_state, eosdom_v)
1112 if (use_stanley)
then
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))
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))
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)
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
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
1887 type(
diag_ctrl),
target,
intent(inout) :: diag
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
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)
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