55 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, clock_routine
74 implicit none ;
private 76 #include <MOM_memory.h> 96 real :: htbl_shelf_min
100 logical :: bottomdraglaw
105 logical :: bbl_use_eos
107 logical :: linear_drag
108 logical :: channel_drag
112 logical :: dynamic_viscous_ml
128 integer :: id_bbl_thick_u = -1, id_kv_bbl_u = -1
129 integer :: id_bbl_thick_v = -1, id_kv_bbl_v = -1
130 integer :: id_ray_u = -1, id_ray_v = -1
131 integer :: id_nkml_visc_u = -1, id_nkml_visc_v = -1
149 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
151 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
153 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
184 real,
dimension(SZIB_(G)) :: &
202 real,
dimension(SZIB_(G),SZJ_(G)) :: &
206 real,
dimension(SZI_(G),SZJB_(G)) :: &
210 real,
dimension(SZIB_(G),SZK_(G)) :: &
251 real :: v_at_u, u_at_v
254 real,
dimension(SZI_(G),SZJ_(G),max(GV%nk_rho_varies,1)) :: &
256 real :: p_ref(szi_(g))
264 real :: a_3, a_12, C24_a
267 real :: apb_4a, ax2_3apb
268 real :: a2x48_apb3, Iapb, Ibma_2
299 real :: H_to_m, m_to_H
309 real :: BBL_visc_frac
311 real,
parameter :: C1_3 = 1.0/3.0, c1_6 = 1.0/6.0, c1_12 = 1.0/12.0
314 real :: tmp_val_m1_to_p1
315 logical :: use_BBL_EOS, do_i(szib_(g))
316 integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, m, n, K2, nkmb, nkml
317 integer :: itt, maxitt=20
320 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
321 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
322 nkmb = gv%nk_rho_varies ; nkml = gv%nkml
323 h_neglect = gv%H_subroundoff
324 rho0x400_g = 400.0*(gv%Rho0/gv%g_Earth)*gv%m_to_H
325 vol_quit = 0.9*gv%Angstrom + h_neglect
326 h_to_m = gv%H_to_m ; m_to_h = gv%m_to_H
327 c2pi_3 = 8.0*atan(1.0)/3.0
329 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_vert_friction(BBL): "//&
330 "Module must be initialized before it is used.")
331 if (.not.cs%bottomdraglaw)
return 333 use_bbl_eos =
associated(tv%eqn_of_state) .and. cs%BBL_use_EOS
336 u_bg_sq = cs%drag_bg_vel * cs%drag_bg_vel
337 cdrag_sqrt=sqrt(cs%cdrag)
343 if ((nkml>0) .and. .not.use_bbl_eos)
then 344 do i=g%IscB,g%IecB+1 ; p_ref(i) = tv%P_ref ;
enddo 346 do j=jsq,jeq+1 ;
do k=1,nkmb
348 rml(:,j,k), isq, ieq-isq+2, tv%eqn_of_state)
353 do j=js-1,je ;
do i=is-1,ie+1
354 d_v(i,j) = 0.5*(g%bathyT(i,j) + g%bathyT(i,j+1))
355 mask_v(i,j) = g%mask2dCv(i,j)
358 do j=js-1,je+1 ;
do i=is-1,ie
359 d_u(i,j) = 0.5*(g%bathyT(i,j) + g%bathyT(i+1,j))
360 mask_u(i,j) = g%mask2dCu(i,j)
363 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
364 if (.not. obc%segment(n)%on_pe) cycle
366 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
367 if (obc%segment(n)%is_N_or_S .and. (j >= js-1) .and. (j <= je))
then 368 do i = max(is-1,obc%segment(n)%HI%isd), min(ie+1,obc%segment(n)%HI%ied)
369 if (obc%segment(n)%direction == obc_direction_n) d_v(i,j) = g%bathyT(i,j)
370 if (obc%segment(n)%direction == obc_direction_s) d_v(i,j) = g%bathyT(i,j+1)
372 elseif (obc%segment(n)%is_E_or_W .and. (i >= is-1) .and. (i <= ie))
then 373 do j = max(js-1,obc%segment(n)%HI%jsd), min(je+1,obc%segment(n)%HI%jed)
374 if (obc%segment(n)%direction == obc_direction_e) d_u(i,j) = g%bathyT(i,j)
375 if (obc%segment(n)%direction == obc_direction_w) d_u(i,j) = g%bathyT(i+1,j)
379 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
382 if (.not. obc%segment(n)%on_pe) cycle
384 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
385 if (obc%segment(n)%is_N_or_S .and. (j >= js-1) .and. (j <= je))
then 386 do i = max(is-1,obc%segment(n)%HI%IsdB), min(ie,obc%segment(n)%HI%IedB)
387 if (obc%segment(n)%direction == obc_direction_n)
then 388 d_u(i,j+1) = d_u(i,j) ; mask_u(i,j+1) = 0.0
389 elseif (obc%segment(n)%direction == obc_direction_s)
then 390 d_u(i,j) = d_u(i,j+1) ; mask_u(i,j) = 0.0
393 elseif (obc%segment(n)%is_E_or_W .and. (i >= is-1) .and. (i <= ie))
then 394 do j = max(js-1,obc%segment(n)%HI%JsdB), min(je,obc%segment(n)%HI%JedB)
395 if (obc%segment(n)%direction == obc_direction_e)
then 396 d_v(i+1,j) = d_v(i,j) ; mask_v(i+1,j) = 0.0
397 elseif (obc%segment(n)%direction == obc_direction_w)
then 398 d_v(i,j) = d_v(i+1,j) ; mask_v(i,j) = 0.0
404 if (.not.use_bbl_eos) rml_vel(:,:) = 0.0
420 do j=g%JscB,g%JecB ;
do m=1,2
424 is = g%IscB ; ie = g%IecB
427 if (g%mask2dCu(i,j) > 0) do_i(i) = .true.
430 is = g%isc ; ie = g%iec
433 if (g%mask2dCv(i,j) > 0) do_i(i) = .true.
438 do k=1,nz ;
do i=is,ie
440 if (u(i,j,k) *(h(i+1,j,k) - h(i,j,k)) >= 0)
then 441 h_at_vel(i,k) = 2.0*h(i,j,k)*h(i+1,j,k) / &
442 (h(i,j,k) + h(i+1,j,k) + h_neglect)
444 h_at_vel(i,k) = 0.5 * (h(i,j,k) + h(i+1,j,k))
447 h_vel(i,k) = 0.5 * (h(i,j,k) + h(i+1,j,k))
449 if (use_bbl_eos)
then ;
do k=1,nz ;
do i=is,ie
451 t_vel(i,k) = 0.5 * (tv%T(i,j,k) + tv%T(i+1,j,k))
452 s_vel(i,k) = 0.5 * (tv%S(i,j,k) + tv%S(i+1,j,k))
453 enddo ;
enddo ;
else ;
do k=1,nkmb ;
do i=is,ie
454 rml_vel(i,k) = 0.5 * (rml(i,j,k) + rml(i+1,j,k))
455 enddo ;
enddo ;
endif 457 do k=1,nz ;
do i=is,ie
459 if (v(i,j,k) * (h(i,j+1,k) - h(i,j,k)) >= 0)
then 460 h_at_vel(i,k) = 2.0*h(i,j,k)*h(i,j+1,k) / &
461 (h(i,j,k) + h(i,j+1,k) + h_neglect)
463 h_at_vel(i,k) = 0.5 * (h(i,j,k) + h(i,j+1,k))
466 h_vel(i,k) = 0.5 * (h(i,j,k) + h(i,j+1,k))
468 if (use_bbl_eos)
then ;
do k=1,nz ;
do i=is,ie
469 t_vel(i,k) = 0.5 * (tv%T(i,j,k) + tv%T(i,j+1,k))
470 s_vel(i,k) = 0.5 * (tv%S(i,j,k) + tv%S(i,j+1,k))
471 enddo ;
enddo ;
else ;
do k=1,nkmb ;
do i=is,ie
472 rml_vel(i,k) = 0.5 * (rml(i,j,k) + rml(i,j+1,k))
473 enddo ;
enddo ;
endif 476 if (
associated(obc))
then ;
if (obc%number_of_segments > 0)
then 479 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_u(i,j) /= obc_none))
then 480 if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e)
then 482 h_at_vel(i,k) = h(i,j,k) ; h_vel(i,k) = h(i,j,k)
484 if (use_bbl_eos)
then 486 t_vel(i,k) = tv%T(i,j,k) ; s_vel(i,k) = tv%S(i,j,k)
490 rml_vel(i,k) = rml(i,j,k)
493 elseif (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_w)
then 495 h_at_vel(i,k) = h(i+1,j,k) ; h_vel(i,k) = h(i+1,j,k)
497 if (use_bbl_eos)
then 499 t_vel(i,k) = tv%T(i+1,j,k) ; s_vel(i,k) = tv%S(i+1,j,k)
503 rml_vel(i,k) = rml(i+1,j,k)
509 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_v(i,j) /= obc_none))
then 510 if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n)
then 512 h_at_vel(i,k) = h(i,j,k) ; h_vel(i,k) = h(i,j,k)
514 if (use_bbl_eos)
then 516 t_vel(i,k) = tv%T(i,j,k) ; s_vel(i,k) = tv%S(i,j,k)
520 rml_vel(i,k) = rml(i,j,k)
523 elseif (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_s)
then 525 h_at_vel(i,k) = h(i,j+1,k) ; h_vel(i,k) = h(i,j+1,k)
527 if (use_bbl_eos)
then 529 t_vel(i,k) = tv%T(i,j+1,k) ; s_vel(i,k) = tv%S(i,j+1,k)
533 rml_vel(i,k) = rml(i,j+1,k)
541 if (use_bbl_eos .or. .not.cs%linear_drag)
then 542 do i=is,ie ;
if (do_i(i))
then 546 htot_vel = 0.0 ; hwtot = 0.0 ; hutot = 0.0
547 thtot = 0.0 ; shtot = 0.0
550 if (htot_vel>=cs%Hbbl)
exit 552 hweight = min(cs%Hbbl - htot_vel, h_at_vel(i,k))
553 if (hweight < 1.5*gv%Angstrom + h_neglect) cycle
555 htot_vel = htot_vel + h_at_vel(i,k)
556 hwtot = hwtot + hweight
558 if ((.not.cs%linear_drag) .and. (hweight >= 0.0))
then ;
if (m==1)
then 560 hutot = hutot + hweight * sqrt(u(i,j,k)*u(i,j,k) + &
561 v_at_u*v_at_u + u_bg_sq)
564 hutot = hutot + hweight * sqrt(v(i,j,k)*v(i,j,k) + &
565 u_at_v*u_at_v + u_bg_sq)
568 if (use_bbl_eos .and. (hweight >= 0.0))
then 569 thtot = thtot + hweight * t_vel(i,k)
570 shtot = shtot + hweight * s_vel(i,k)
574 if (.not.cs%linear_drag .and. (hwtot > 0.0))
then 575 ustar(i) = cdrag_sqrt*hutot/hwtot
577 ustar(i) = cdrag_sqrt*cs%drag_bg_vel
580 if (use_bbl_eos)
then ;
if (hwtot > 0.0)
then 581 t_eos(i) = thtot/hwtot ; s_eos(i) = shtot/hwtot
583 t_eos(i) = 0.0 ; s_eos(i) = 0.0
587 do i=is,ie ; ustar(i) = cdrag_sqrt*cs%drag_bg_vel ;
enddo 590 if (use_bbl_eos)
then 593 if (.not.do_i(i))
then ; t_eos(i) = 0.0 ; s_eos(i) = 0.0 ;
endif 595 do k=1,nz ;
do i=is,ie
596 press(i) = press(i) + gv%H_to_Pa * h_vel(i,k)
599 is-g%IsdB+1, ie-is+1, tv%eqn_of_state)
602 do i=is,ie ;
if (do_i(i))
then 605 ustarsq = rho0x400_g * ustar(i)**2
612 if (use_bbl_eos)
then 613 thtot = 0.0 ; shtot = 0.0 ; oldfn = 0.0
615 if (h_at_vel(i,k) <= 0.0) cycle
617 oldfn = dr_dt(i)*(thtot - t_vel(i,k)*htot) + &
618 dr_ds(i)*(shtot - s_vel(i,k)*htot)
619 if (oldfn >= ustarsq)
exit 621 dfn = (dr_dt(i)*(t_vel(i,k) - t_vel(i,k-1)) + &
622 dr_ds(i)*(s_vel(i,k) - s_vel(i,k-1))) * &
623 (h_at_vel(i,k) + htot)
625 if ((oldfn + dfn) <= ustarsq)
then 628 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn)/dfn)
632 thtot = thtot + t_vel(i,k)*dh ; shtot = shtot + s_vel(i,k)*dh
634 if ((oldfn < ustarsq) .and. h_at_vel(i,1) > 0.0)
then 636 if (dr_dt(i) * (thtot - t_vel(i,1)*htot) + &
637 dr_ds(i) * (shtot - s_vel(i,1)*htot) < ustarsq) &
638 htot = htot + h_at_vel(i,1)
643 oldfn = rhtot - gv%Rlay(k)*htot
644 dfn = (gv%Rlay(k) - gv%Rlay(k-1))*(h_at_vel(i,k)+htot)
646 if (oldfn >= ustarsq)
then 648 else if ((oldfn + dfn) <= ustarsq)
then 651 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn)/dfn)
655 rhtot = rhtot + gv%Rlay(k)*dh
659 oldfn = rhtot - rml_vel(i,k)*htot
660 dfn = (rml_vel(i,k) - rml_vel(i,k-1)) * (h_at_vel(i,k)+htot)
662 if (oldfn >= ustarsq)
then 664 else if ((oldfn + dfn) <= ustarsq)
then 667 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn)/dfn)
671 rhtot = rhtot + rml_vel(i,k)*dh
673 if (rhtot - rml_vel(i,1)*htot < ustarsq) htot = htot + h_at_vel(i,1)
675 if (rhtot - gv%Rlay(1)*htot < ustarsq) htot = htot + h_at_vel(i,1)
683 if (m==1)
then ; c2f = (g%CoriolisBu(i,j-1)+g%CoriolisBu(i,j))
684 else ; c2f = (g%CoriolisBu(i-1,j)+g%CoriolisBu(i,j)) ;
endif 686 if (cs%cdrag * u_bg_sq <= 0.0)
then 689 usth = ustar(i)*m_to_h ; root = sqrt(0.25*usth**2 + (htot*c2f)**2)
690 if (htot*usth <= (cs%BBL_thick_min+h_neglect) * (0.5*usth + root))
then 691 bbl_thick = cs%BBL_thick_min
693 bbl_thick = (htot * usth) / (0.5*usth + root)
696 bbl_thick = htot / (0.5 + sqrt(0.25 + htot*htot*c2f*c2f/ &
697 ((ustar(i)*ustar(i)) * (m_to_h**2) )))
699 if (bbl_thick < cs%BBL_thick_min) bbl_thick = cs%BBL_thick_min
706 if ((bbl_thick > 0.5*cs%Hbbl) .and. (cs%RiNo_mix)) bbl_thick = 0.5*cs%Hbbl
708 if (cs%Channel_drag)
then 714 tmp = g%mask2dCu(i,j+1) * d_u(i,j+1)
715 dp = 2.0 * d_vel * tmp / (d_vel + tmp)
716 tmp = g%mask2dCu(i,j-1) * d_u(i,j-1)
717 dm = 2.0 * d_vel * tmp / (d_vel + tmp)
720 tmp = g%mask2dCv(i+1,j) * d_v(i+1,j)
721 dp = 2.0 * d_vel * tmp / (d_vel + tmp)
722 tmp = g%mask2dCv(i-1,j) * d_v(i-1,j)
723 dm = 2.0 * d_vel * tmp / (d_vel + tmp)
725 if (dm > dp)
then ; tmp = dp ; dp = dm ; dm = tmp ;
endif 728 dp = m_to_h*dp ; dm = m_to_h*dm ; d_vel = m_to_h*d_vel
730 a_3 = (dp + dm - 2.0*d_vel) ; a = 3.0*a_3 ; a_12 = 0.25*a_3
734 if (abs(a) < 1e-2*(slope + cs%BBL_thick_min)) a = 0.0
742 vol_open = d_vel - dm ; vol_2_reg = vol_open
745 vol_open = 0.25*slope*tmp + c1_12*a
746 vol_2_reg = 0.5*tmp**2 * (a - c1_3*slope)
749 c24_a = 24.0/a ; iapb = 1.0/(a+slope)
750 apb_4a = (slope+a)/(4.0*a) ; a2x48_apb3 = (48.0*(a*a))*(iapb**3)
751 ax2_3apb = 2.0*c1_3*a*iapb
752 elseif (a == 0.0)
then 754 if (slope > 0) iapb = 1.0/slope
756 vol_open = d_vel - dm
757 if (slope >= -a)
then 758 iapb = 1.0e30 ;
if (slope+a /= 0.0) iapb = 1.0/(a+slope)
759 vol_direct = 0.0 ; l_direct = 0.0 ; c24_a = 0.0
761 c24_a = 24.0/a ; iapb = 1.0/(a+slope)
762 l_direct = 1.0 + slope/a
763 vol_direct = -c1_6*a*l_direct**3
765 ibma_2 = 2.0 / (slope - a)
768 l(nz+1) = 0.0 ; vol = 0.0 ; vol_err = 0.0 ; bbl_visc_frac = 0.0
773 vol = vol + h_vel(i,k)
774 h_vel_pos = h_vel(i,k) + h_neglect
776 if (vol >= vol_open)
then ; l(k) = 1.0
778 l(k) = sqrt(2.0*vol*iapb)
782 if (vol < vol_2_reg)
then 785 if (a2x48_apb3*vol < 1e-8)
then 787 l0 = sqrt(2.0*vol*iapb) ; l(k) = l0*(1.0 + ax2_3apb*l0)
789 l(k) = apb_4a * (1.0 - &
790 2.0 * cos(c1_3*acos(a2x48_apb3*vol - 1.0) - c2pi_3))
798 tmp_val_m1_to_p1 = 1.0 - c24_a*(vol_open - vol)
799 tmp_val_m1_to_p1 = max(-1., min(1., tmp_val_m1_to_p1))
800 l(k) = 0.5 - cos(c1_3*acos(tmp_val_m1_to_p1) - c2pi_3)
805 if (vol <= vol_direct)
then 807 l(k) = (-0.25*c24_a*vol)**c1_3
815 if (vol_below + vol_err <= vol_direct)
then 816 l0 = l_direct ; vol_0 = vol_direct
818 l0 = l(k+1) ; vol_0 = vol_below + vol_err
824 dv_dl2 = 0.5*(slope+a) - a*l0 ; dvol = (vol-vol_0)
837 if (a*a*dvol**3 < gv%Angstrom*dv_dl2**2 * &
838 (0.25*dv_dl2*gv%Angstrom - a*l0*dvol))
then 841 l(k) = sqrt(l0*l0 + dvol / dv_dl2)
842 vol_err = 0.5*(l(k)*l(k))*(slope + a_3*(3.0-4.0*l(k))) - vol
844 if (dv_dl2*(1.0-l0*l0) < dvol + &
845 dv_dl2 * (vol_open - vol)*ibma_2)
then 846 l_max = sqrt(1.0 - (vol_open - vol)*ibma_2)
848 l_max = sqrt(l0*l0 + dvol / dv_dl2)
850 l_min = sqrt(l0*l0 + dvol / (0.5*(slope+a) - a*l_max))
852 vol_err_min = 0.5*(l_min**2)*(slope + a_3*(3.0-4.0*l_min)) - vol
853 vol_err_max = 0.5*(l_max**2)*(slope + a_3*(3.0-4.0*l_max)) - vol
855 if (abs(vol_err_min) <= vol_quit)
then 856 l(k) = l_min ; vol_err = vol_err_min
858 l(k) = sqrt((l_min**2*vol_err_max - l_max**2*vol_err_min) / &
859 (vol_err_max - vol_err_min))
861 vol_err = 0.5*(l(k)*l(k))*(slope + a_3*(3.0-4.0*l(k))) - vol
862 if (abs(vol_err) <= vol_quit)
exit 865 l(k) = l(k) - vol_err / (l(k)* (slope + a - 2.0*a*l(k)))
876 if (l(k) > l(k+1))
then 877 if (vol_below < bbl_thick)
then 878 bbl_frac = (1.0-vol_below/bbl_thick)**2
879 bbl_visc_frac = bbl_visc_frac + bbl_frac*(l(k) - l(k+1))
884 if (m==1)
then ; cell_width = g%dy_Cu(i,j)
885 else ; cell_width = g%dx_Cv(i,j) ;
endif 886 gam = 1.0 - l(k+1)/l(k)
887 rayleigh = cs%cdrag * (l(k)-l(k+1)) * (1.0-bbl_frac) * &
888 (12.0*cs%c_Smag*h_vel_pos) / (12.0*cs%c_Smag*h_vel_pos + m_to_h * &
889 cs%cdrag * gam*(1.0-gam)*(1.0-1.5*gam) * l(k)**2 * cell_width)
895 if (rayleigh > 0.0)
then 897 visc%Ray_u(i,j,k) = rayleigh*sqrt(u(i,j,k)*u(i,j,k) + &
898 v_at_u*v_at_u + u_bg_sq)
899 else ; visc%Ray_u(i,j,k) = 0.0 ;
endif 901 if (rayleigh > 0.0)
then 903 visc%Ray_v(i,j,k) = rayleigh*sqrt(v(i,j,k)*v(i,j,k) + &
904 u_at_v*u_at_v + u_bg_sq)
905 else ; visc%Ray_v(i,j,k) = 0.0 ;
endif 910 bbl_thick = bbl_thick * h_to_m
912 visc%kv_bbl_u(i,j) = max(cs%KV_BBL_min, &
913 cdrag_sqrt*ustar(i)*bbl_thick*bbl_visc_frac)
914 visc%bbl_thick_u(i,j) = bbl_thick
916 visc%kv_bbl_v(i,j) = max(cs%KV_BBL_min, &
917 cdrag_sqrt*ustar(i)*bbl_thick*bbl_visc_frac)
918 visc%bbl_thick_v(i,j) = bbl_thick
924 bbl_thick = bbl_thick * h_to_m
926 visc%kv_bbl_u(i,j) = max(cs%KV_BBL_min, cdrag_sqrt*ustar(i)*bbl_thick)
927 visc%bbl_thick_u(i,j) = bbl_thick
929 visc%kv_bbl_v(i,j) = max(cs%KV_BBL_min, cdrag_sqrt*ustar(i)*bbl_thick)
930 visc%bbl_thick_v(i,j) = bbl_thick
937 if (cs%id_bbl_thick_u > 0) &
938 call post_data(cs%id_bbl_thick_u, visc%bbl_thick_u, cs%diag)
939 if (cs%id_kv_bbl_u > 0) &
940 call post_data(cs%id_kv_bbl_u, visc%kv_bbl_u, cs%diag)
941 if (cs%id_bbl_thick_v > 0) &
942 call post_data(cs%id_bbl_thick_v, visc%bbl_thick_v, cs%diag)
943 if (cs%id_kv_bbl_v > 0) &
944 call post_data(cs%id_kv_bbl_v, visc%kv_bbl_v, cs%diag)
945 if (cs%id_Ray_u > 0) &
946 call post_data(cs%id_Ray_u, visc%Ray_u, cs%diag)
947 if (cs%id_Ray_v > 0) &
948 call post_data(cs%id_Ray_v, visc%Ray_v, cs%diag)
951 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v)) &
952 call uvchksum(
"Ray [uv]", visc%Ray_u, visc%Ray_v, g%HI,haloshift=0)
953 if (
associated(visc%kv_bbl_u) .and.
associated(visc%kv_bbl_v)) &
954 call uvchksum(
"kv_bbl_[uv]", visc%kv_bbl_u, visc%kv_bbl_v, g%HI,haloshift=0)
955 if (
associated(visc%bbl_thick_u) .and.
associated(visc%bbl_thick_v)) &
956 call uvchksum(
"bbl_thick_[uv]", visc%bbl_thick_u, &
957 visc%bbl_thick_v, g%HI,haloshift=0)
963 function set_v_at_u(v, h, G, i, j, k, mask2dCv)
965 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
966 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
967 integer,
intent(in) :: i, j, k
968 real,
dimension(SZI_(G),SZJB_(G)),
intent(in) :: mask2dCv
975 hwt(1) = (h(i,j-1,k) + h(i,j,k)) * mask2dcv(i,j-1)
976 hwt(2) = (h(i+1,j-1,k) + h(i+1,j,k)) * mask2dcv(i+1,j-1)
977 hwt(3) = (h(i,j,k) + h(i,j+1,k)) * mask2dcv(i,j)
978 hwt(4) = (h(i+1,j,k) + h(i+1,j+1,k)) * mask2dcv(i+1,j)
980 hwt_tot = (hwt(1) + hwt(4)) + (hwt(2) + hwt(3))
982 if (hwt_tot > 0.0) set_v_at_u = &
983 ((hwt(3) * v(i,j,k) + hwt(2) * v(i+1,j-1,k)) + &
984 (hwt(4) * v(i+1,j,k) + hwt(1) * v(i,j-1,k))) / hwt_tot
988 function set_u_at_v(u, h, G, i, j, k, mask2dCu)
990 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
991 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
992 real,
dimension(SZIB_(G),SZJ_(G)),
intent(in) :: mask2dCu
993 integer,
intent(in) :: i, j, k
1000 hwt(1) = (h(i-1,j,k) + h(i,j,k)) * mask2dcu(i-1,j)
1001 hwt(2) = (h(i,j,k) + h(i+1,j,k)) * mask2dcu(i,j)
1002 hwt(3) = (h(i-1,j+1,k) + h(i,j+1,k)) * mask2dcu(i-1,j+1)
1003 hwt(4) = (h(i,j+1,k) + h(i+1,j+1,k)) * mask2dcu(i,j+1)
1005 hwt_tot = (hwt(1) + hwt(4)) + (hwt(2) + hwt(3))
1007 if (hwt_tot > 0.0) set_u_at_v = &
1008 ((hwt(2) * u(i,j,k) + hwt(3) * u(i-1,j+1,k)) + &
1009 (hwt(1) * u(i-1,j,k) + hwt(4) * u(i,j+1,k))) / hwt_tot
1017 subroutine set_viscous_ml(u, v, h, tv, fluxes, visc, dt, G, GV, CS)
1020 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
1022 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1024 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1029 type(
forcing),
intent(in) :: fluxes
1034 real,
intent(in) :: dt
1060 real,
dimension(SZIB_(G)) :: &
1083 real,
dimension(SZIB_(G),SZJ_(G)) :: &
1086 real,
dimension(SZI_(G),SZJB_(G)) :: &
1089 real :: h_at_vel(szib_(g),szk_(g))
1092 integer :: k_massive(szib_(g))
1148 real :: H_to_m, m_to_H
1151 logical :: use_EOS, do_any, do_any_shelf, do_i(szib_(g))
1152 integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, K2, nkmb, nkml, n
1155 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1156 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
1157 nkmb = gv%nk_rho_varies ; nkml = gv%nkml
1159 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_vert_friction(visc_ML): "//&
1160 "Module must be initialized before it is used.")
1161 if (.not.(cs%dynamic_viscous_ML .or.
associated(fluxes%frac_shelf_h)))
return 1163 rho0x400_g = 400.0*(gv%Rho0/gv%g_Earth)*gv%m_to_H
1164 u_bg_sq = cs%drag_bg_vel * cs%drag_bg_vel
1165 cdrag_sqrt=sqrt(cs%cdrag)
1168 use_eos =
associated(tv%eqn_of_state)
1169 dt_rho0 = dt/gv%H_to_kg_m2
1170 h_neglect = gv%H_subroundoff
1171 h_tiny = 2.0*gv%Angstrom + h_neglect
1172 g_h_rho0 = (gv%g_Earth * gv%H_to_m) / gv%Rho0
1173 h_to_m = gv%H_to_m ; m_to_h = gv%m_to_H
1175 if (
associated(fluxes%frac_shelf_h))
then 1178 if (.not.
associated(fluxes%frac_shelf_u))
call mom_error(fatal, &
1179 "set_viscous_ML: fluxes%frac_shelf_h is associated, but " // &
1180 "fluxes%frac_shelf_u is not.")
1181 if (.not.
associated(fluxes%frac_shelf_v))
call mom_error(fatal, &
1182 "set_viscous_ML: fluxes%frac_shelf_h is associated, but " // &
1183 "fluxes%frac_shelf_v is not.")
1184 if (.not.
associated(visc%taux_shelf))
then 1185 allocate(visc%taux_shelf(g%IsdB:g%IedB,g%jsd:g%jed))
1186 visc%taux_shelf(:,:) = 0.0
1188 if (.not.
associated(visc%tauy_shelf))
then 1189 allocate(visc%tauy_shelf(g%isd:g%ied,g%JsdB:g%JedB))
1190 visc%tauy_shelf(:,:) = 0.0
1192 if (.not.
associated(visc%tbl_thick_shelf_u))
then 1193 allocate(visc%tbl_thick_shelf_u(g%IsdB:g%IedB,g%jsd:g%jed))
1194 visc%tbl_thick_shelf_u(:,:) = 0.0
1196 if (.not.
associated(visc%tbl_thick_shelf_v))
then 1197 allocate(visc%tbl_thick_shelf_v(g%isd:g%ied,g%JsdB:g%JedB))
1198 visc%tbl_thick_shelf_v(:,:) = 0.0
1200 if (.not.
associated(visc%kv_tbl_shelf_u))
then 1201 allocate(visc%kv_tbl_shelf_u(g%IsdB:g%IedB,g%jsd:g%jed))
1202 visc%kv_tbl_shelf_u(:,:) = 0.0
1204 if (.not.
associated(visc%kv_tbl_shelf_v))
then 1205 allocate(visc%kv_tbl_shelf_v(g%isd:g%ied,g%JsdB:g%JedB))
1206 visc%kv_tbl_shelf_v(:,:) = 0.0
1214 do j=js-1,je ;
do i=is-1,ie+1
1215 mask_v(i,j) = g%mask2dCv(i,j)
1218 do j=js-1,je+1 ;
do i=is-1,ie
1219 mask_u(i,j) = g%mask2dCu(i,j)
1222 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
1225 if (.not. obc%segment(n)%on_pe) cycle
1227 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
1228 if (obc%segment(n)%is_N_or_S .and. (j >= js-1) .and. (j <= je))
then 1229 do i = max(is-1,obc%segment(n)%HI%IsdB), min(ie,obc%segment(n)%HI%IedB)
1230 if (obc%segment(n)%direction == obc_direction_n) mask_u(i,j+1) = 0.0
1231 if (obc%segment(n)%direction == obc_direction_s) mask_u(i,j) = 0.0
1233 elseif (obc%segment(n)%is_E_or_W .and. (i >= is-1) .and. (i <= je))
then 1234 do j = max(js-1,obc%segment(n)%HI%JsdB), min(je,obc%segment(n)%HI%JedB)
1235 if (obc%segment(n)%direction == obc_direction_e) mask_v(i+1,j) = 0.0
1236 if (obc%segment(n)%direction == obc_direction_w) mask_v(i,j) = 0.0
1252 if (cs%dynamic_viscous_ML)
then 1256 if (g%mask2dCu(i,j) < 0.5)
then 1257 do_i(i) = .false. ; visc%nkml_visc_u(i,j) = nkml
1259 do_i(i) = .true. ; do_any = .true.
1261 thtot(i) = 0.0 ; shtot(i) = 0.0 ; rhtot(i) = 0.0
1262 uhtot(i) = dt_rho0 * fluxes%taux(i,j)
1263 vhtot(i) = 0.25 * dt_rho0 * ((fluxes%tauy(i,j) + fluxes%tauy(i+1,j-1)) + &
1264 (fluxes%tauy(i,j-1) + fluxes%tauy(i+1,j)))
1266 if (cs%omega_frac >= 1.0)
then ; absf = 2.0*cs%omega ;
else 1267 absf = 0.5*(abs(g%CoriolisBu(i,j)) + abs(g%CoriolisBu(i,j-1)))
1268 if (cs%omega_frac > 0.0) &
1269 absf = sqrt(cs%omega_frac*4.0*cs%omega**2 + (1.0-cs%omega_frac)*absf**2)
1271 u_star = max(cs%ustar_min, 0.5 * (fluxes%ustar(i,j) + fluxes%ustar(i+1,j)))
1272 idecay_len_tke(i) = ((absf / u_star) * cs%TKE_decay) * h_to_m
1276 if (do_any)
then ;
do k=1,nz
1279 if (use_eos .and. (k==nkml+1))
then 1282 press(i) = gv%H_to_Pa * htot(i)
1284 i_2hlay = 1.0 / (h(i,j,k2) + h(i+1,j,k2) + h_neglect)
1285 t_eos(i) = (h(i,j,k2)*tv%T(i,j,k2) + h(i+1,j,k2)*tv%T(i+1,j,k2)) * i_2hlay
1286 s_eos(i) = (h(i,j,k2)*tv%S(i,j,k2) + h(i+1,j,k2)*tv%S(i+1,j,k2)) * i_2hlay
1289 isq-g%IsdB+1, ieq-isq+1, tv%eqn_of_state)
1292 do i=isq,ieq ;
if (do_i(i))
then 1294 hlay = 0.5*(h(i,j,k) + h(i+1,j,k))
1295 if (hlay > h_tiny)
then 1296 i_2hlay = 1.0 / (h(i,j,k) + h(i+1,j,k))
1297 v_at_u = 0.5 * (h(i,j,k) * (v(i,j,k) + v(i,j-1,k)) + &
1298 h(i+1,j,k) * (v(i+1,j,k) + v(i+1,j-1,k))) * i_2hlay
1299 uh2 = (uhtot(i) - htot(i)*u(i,j,k))**2 + (vhtot(i) - htot(i)*v_at_u)**2
1302 t_lay = (h(i,j,k)*tv%T(i,j,k) + h(i+1,j,k)*tv%T(i+1,j,k)) * i_2hlay
1303 s_lay = (h(i,j,k)*tv%S(i,j,k) + h(i+1,j,k)*tv%S(i+1,j,k)) * i_2hlay
1304 ghprime = g_h_rho0 * (dr_dt(i) * (t_lay*htot(i) - thtot(i)) + &
1305 dr_ds(i) * (s_lay*htot(i) - shtot(i)))
1307 ghprime = g_h_rho0 * (gv%Rlay(k)*htot(i) - rhtot(i))
1310 if (ghprime > 0.0)
then 1311 ribulk = cs%bulk_Ri_ML * exp(-htot(i) * idecay_len_tke(i))
1312 if (ribulk * uh2 <= (htot(i)**2) * ghprime)
then 1313 visc%nkml_visc_u(i,j) =
real(k_massive(i))
1315 elseif (ribulk * uh2 <= (htot(i) + hlay)**2 * ghprime)
then 1316 visc%nkml_visc_u(i,j) =
real(k-1) + &
1317 ( sqrt(ribulk * uh2 / ghprime) - htot(i) ) / hlay
1324 if (do_i(i)) do_any = .true.
1327 if (.not.do_any)
exit 1330 do i=isq,ieq ;
if (do_i(i))
then 1331 htot(i) = htot(i) + 0.5 * (h(i,j,k) + h(i+1,j,k))
1332 uhtot(i) = uhtot(i) + 0.5 * (h(i,j,k) + h(i+1,j,k)) * u(i,j,k)
1333 vhtot(i) = vhtot(i) + 0.25 * (h(i,j,k) * (v(i,j,k) + v(i,j-1,k)) + &
1334 h(i+1,j,k) * (v(i+1,j,k) + v(i+1,j-1,k)))
1336 thtot(i) = thtot(i) + 0.5 * (h(i,j,k)*tv%T(i,j,k) + h(i+1,j,k)*tv%T(i+1,j,k))
1337 shtot(i) = shtot(i) + 0.5 * (h(i,j,k)*tv%S(i,j,k) + h(i+1,j,k)*tv%S(i+1,j,k))
1339 rhtot(i) = rhtot(i) + 0.5 * (h(i,j,k) + h(i+1,j,k)) * gv%Rlay(k)
1344 if (do_any)
then ;
do i=isq,ieq ;
if (do_i(i))
then 1345 visc%nkml_visc_u(i,j) = k_massive(i)
1346 endif ;
enddo ;
endif 1349 do_any_shelf = .false.
1350 if (
associated(fluxes%frac_shelf_h))
then 1352 if (fluxes%frac_shelf_u(i,j)*g%mask2dCu(i,j) == 0.0)
then 1354 visc%tbl_thick_shelf_u(i,j) = 0.0 ; visc%kv_tbl_shelf_u(i,j) = 0.0
1356 do_i(i) = .true. ; do_any_shelf = .true.
1361 if (do_any_shelf)
then 1362 do k=1,nz ;
do i=isq,ieq ;
if (do_i(i))
then 1363 if (u(i,j,k) *(h(i+1,j,k) - h(i,j,k)) >= 0)
then 1364 h_at_vel(i,k) = 2.0*h(i,j,k)*h(i+1,j,k) / &
1365 (h(i,j,k) + h(i+1,j,k) + h_neglect)
1367 h_at_vel(i,k) = 0.5 * (h(i,j,k) + h(i+1,j,k))
1370 h_at_vel(i,k) = 0.0 ; ustar(i) = 0.0
1371 endif ;
enddo ;
enddo 1373 do i=isq,ieq ;
if (do_i(i))
then 1374 htot_vel = 0.0 ; hwtot = 0.0 ; hutot = 0.0
1375 thtot(i) = 0.0 ; shtot(i) = 0.0
1376 if (use_eos .or. .not.cs%linear_drag)
then ;
do k=1,nz
1377 if (htot_vel>=cs%Htbl_shelf)
exit 1378 hweight = min(cs%Htbl_shelf - htot_vel, h_at_vel(i,k))
1379 if (hweight <= 1.5*gv%Angstrom + h_neglect) cycle
1381 htot_vel = htot_vel + h_at_vel(i,k)
1382 hwtot = hwtot + hweight
1384 if (.not.cs%linear_drag)
then 1385 v_at_u =
set_v_at_u(v, h, g, i, j, k, mask_v)
1386 hutot = hutot + hweight * sqrt(u(i,j,k)**2 + &
1387 v_at_u**2 + u_bg_sq)
1390 thtot(i) = thtot(i) + hweight * 0.5 * (tv%T(i,j,k) + tv%T(i+1,j,k))
1391 shtot(i) = shtot(i) + hweight * 0.5 * (tv%S(i,j,k) + tv%S(i+1,j,k))
1395 if ((.not.cs%linear_drag) .and. (hwtot > 0.0))
then 1396 ustar(i) = cdrag_sqrt*hutot/hwtot
1398 ustar(i) = cdrag_sqrt*cs%drag_bg_vel
1401 if (use_eos)
then ;
if (hwtot > 0.0)
then 1402 t_eos(i) = thtot(i)/hwtot ; s_eos(i) = shtot(i)/hwtot
1404 t_eos(i) = 0.0 ; s_eos(i) = 0.0
1410 dr_dt, dr_ds, isq-g%IsdB+1, ieq-isq+1, tv%eqn_of_state)
1413 do i=isq,ieq ;
if (do_i(i))
then 1416 ustarsq = rho0x400_g * ustar(i)**2
1419 thtot(i) = 0.0 ; shtot(i) = 0.0
1421 if (h_at_vel(i,k) <= 0.0) cycle
1422 t_lay = 0.5 * (tv%T(i,j,k) + tv%T(i+1,j,k))
1423 s_lay = 0.5 * (tv%S(i,j,k) + tv%S(i+1,j,k))
1424 oldfn = dr_dt(i)*(t_lay*htot(i) - thtot(i)) + dr_ds(i)*(s_lay*htot(i) - shtot(i))
1425 if (oldfn >= ustarsq)
exit 1427 dfn = (dr_dt(i)*(0.5*(tv%T(i,j,k+1)+tv%T(i+1,j,k+1)) - t_lay) + &
1428 dr_ds(i)*(0.5*(tv%S(i,j,k+1)+tv%S(i+1,j,k+1)) - s_lay)) * &
1429 (h_at_vel(i,k)+htot(i))
1430 if ((oldfn + dfn) <= ustarsq)
then 1433 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn)/dfn)
1436 htot(i) = htot(i) + dh
1437 thtot(i) = thtot(i) + t_lay*dh ; shtot(i) = shtot(i) + s_lay*dh
1439 if ((oldfn < ustarsq) .and. (h_at_vel(i,nz) > 0.0))
then 1440 t_lay = 0.5*(tv%T(i,j,nz) + tv%T(i+1,j,nz))
1441 s_lay = 0.5*(tv%S(i,j,nz) + tv%S(i+1,j,nz))
1442 if (dr_dt(i)*(t_lay*htot(i) - thtot(i)) + &
1443 dr_ds(i)*(s_lay*htot(i) - shtot(i)) < ustarsq) &
1444 htot(i) = htot(i) + h_at_vel(i,nz)
1449 rlay = gv%Rlay(k) ; rlb = gv%Rlay(k+1)
1451 oldfn = rlay*htot(i) - rhtot(i)
1452 if (oldfn >= ustarsq)
exit 1454 dfn = (rlb - rlay)*(h_at_vel(i,k)+htot(i))
1455 if ((oldfn + dfn) <= ustarsq)
then 1458 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn)/dfn)
1461 htot(i) = htot(i) + dh
1462 rhtot(i) = rhtot(i) + rlay*dh
1464 if (gv%Rlay(nz)*htot(i) - rhtot(i) < ustarsq) &
1465 htot(i) = htot(i) + h_at_vel(i,nz)
1472 ustar1 = ustar(i)*m_to_h
1473 h2f2 = (htot(i)*(g%CoriolisBu(i,j-1)+g%CoriolisBu(i,j)) + h_neglect*cs%Omega)**2
1474 visc%tbl_thick_shelf_u(i,j) = max(cs%Htbl_shelf_min, &
1475 ( htot(i)*ustar1 ) / ( 0.5*ustar1 + sqrt((0.5*ustar1)**2 + h2f2 ) ) )
1476 visc%kv_tbl_shelf_u(i,j) = max(cs%KV_TBL_min, &
1477 cdrag_sqrt*ustar(i)*visc%tbl_thick_shelf_u(i,j))
1495 if (cs%dynamic_viscous_ML)
then 1499 if (g%mask2dCv(i,j) < 0.5)
then 1500 do_i(i) = .false. ; visc%nkml_visc_v(i,j) = nkml
1502 do_i(i) = .true. ; do_any = .true.
1504 thtot(i) = 0.0 ; shtot(i) = 0.0 ; rhtot(i) = 0.0
1505 vhtot(i) = dt_rho0 * fluxes%tauy(i,j)
1506 uhtot(i) = 0.25 * dt_rho0 * ((fluxes%taux(i,j) + fluxes%taux(i-1,j+1)) + &
1507 (fluxes%taux(i-1,j) + fluxes%taux(i,j+1)))
1509 if (cs%omega_frac >= 1.0)
then ; absf = 2.0*cs%omega ;
else 1510 absf = 0.5*(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j)))
1511 if (cs%omega_frac > 0.0) &
1512 absf = sqrt(cs%omega_frac*4.0*cs%omega**2 + (1.0-cs%omega_frac)*absf**2)
1515 u_star = max(cs%ustar_min, 0.5 * (fluxes%ustar(i,j) + fluxes%ustar(i,j+1)))
1516 idecay_len_tke(i) = ((absf / u_star) * cs%TKE_decay) * h_to_m
1521 if (do_any)
then ;
do k=1,nz
1524 if (use_eos .and. (k==nkml+1))
then 1527 press(i) = gv%H_to_Pa * htot(i)
1529 i_2hlay = 1.0 / (h(i,j,k2) + h(i,j+1,k2) + h_neglect)
1530 t_eos(i) = (h(i,j,k2)*tv%T(i,j,k2) + h(i,j+1,k2)*tv%T(i,j+1,k2)) * i_2hlay
1531 s_eos(i) = (h(i,j,k2)*tv%S(i,j,k2) + h(i,j+1,k2)*tv%S(i,j+1,k2)) * i_2hlay
1534 is-g%IsdB+1, ie-is+1, tv%eqn_of_state)
1537 do i=is,ie ;
if (do_i(i))
then 1539 hlay = 0.5*(h(i,j,k) + h(i,j+1,k))
1540 if (hlay > h_tiny)
then 1541 i_2hlay = 1.0 / (h(i,j,k) + h(i,j+1,k))
1542 u_at_v = 0.5 * (h(i,j,k) * (u(i-1,j,k) + u(i,j,k)) + &
1543 h(i,j+1,k) * (u(i-1,j+1,k) + u(i,j+1,k))) * i_2hlay
1544 uh2 = (uhtot(i) - htot(i)*u_at_v)**2 + (vhtot(i) - htot(i)*v(i,j,k))**2
1547 t_lay = (h(i,j,k)*tv%T(i,j,k) + h(i,j+1,k)*tv%T(i,j+1,k)) * i_2hlay
1548 s_lay = (h(i,j,k)*tv%S(i,j,k) + h(i,j+1,k)*tv%S(i,j+1,k)) * i_2hlay
1549 ghprime = g_h_rho0 * (dr_dt(i) * (t_lay*htot(i) - thtot(i)) + &
1550 dr_ds(i) * (s_lay*htot(i) - shtot(i)))
1552 ghprime = g_h_rho0 * (gv%Rlay(k)*htot(i) - rhtot(i))
1555 if (ghprime > 0.0)
then 1556 ribulk = cs%bulk_Ri_ML * exp(-htot(i) * idecay_len_tke(i))
1557 if (ribulk * uh2 <= htot(i)**2 * ghprime)
then 1558 visc%nkml_visc_v(i,j) =
real(k_massive(i))
1560 elseif (ribulk * uh2 <= (htot(i) + hlay)**2 * ghprime)
then 1561 visc%nkml_visc_v(i,j) =
real(k-1) + &
1562 ( sqrt(ribulk * uh2 / ghprime) - htot(i) ) / hlay
1569 if (do_i(i)) do_any = .true.
1572 if (.not.do_any)
exit 1575 do i=is,ie ;
if (do_i(i))
then 1576 htot(i) = htot(i) + 0.5 * (h(i,j,k) + h(i,j+1,k))
1577 vhtot(i) = vhtot(i) + 0.5 * (h(i,j,k) + h(i,j+1,k)) * v(i,j,k)
1578 uhtot(i) = uhtot(i) + 0.25 * (h(i,j,k) * (u(i-1,j,k) + u(i,j,k)) + &
1579 h(i,j+1,k) * (u(i-1,j+1,k) + u(i,j+1,k)))
1581 thtot(i) = thtot(i) + 0.5 * (h(i,j,k)*tv%T(i,j,k) + h(i,j+1,k)*tv%T(i,j+1,k))
1582 shtot(i) = shtot(i) + 0.5 * (h(i,j,k)*tv%S(i,j,k) + h(i,j+1,k)*tv%S(i,j+1,k))
1584 rhtot(i) = rhtot(i) + 0.5 * (h(i,j,k) + h(i,j+1,k)) * gv%Rlay(k)
1589 if (do_any)
then ;
do i=is,ie ;
if (do_i(i))
then 1590 visc%nkml_visc_v(i,j) = k_massive(i)
1591 endif ;
enddo ;
endif 1594 do_any_shelf = .false.
1595 if (
associated(fluxes%frac_shelf_h))
then 1597 if (fluxes%frac_shelf_v(i,j)*g%mask2dCv(i,j) == 0.0)
then 1599 visc%tbl_thick_shelf_v(i,j) = 0.0 ; visc%kv_tbl_shelf_v(i,j) = 0.0
1601 do_i(i) = .true. ; do_any_shelf = .true.
1606 if (do_any_shelf)
then 1607 do k=1,nz ;
do i=is,ie ;
if (do_i(i))
then 1608 if (v(i,j,k) * (h(i,j+1,k) - h(i,j,k)) >= 0)
then 1609 h_at_vel(i,k) = 2.0*h(i,j,k)*h(i,j+1,k) / &
1610 (h(i,j,k) + h(i,j+1,k) + h_neglect)
1612 h_at_vel(i,k) = 0.5 * (h(i,j,k) + h(i,j+1,k))
1615 h_at_vel(i,k) = 0.0 ; ustar(i) = 0.0
1616 endif ;
enddo ;
enddo 1618 do i=is,ie ;
if (do_i(i))
then 1619 htot_vel = 0.0 ; hwtot = 0.0 ; hutot = 0.0
1620 thtot(i) = 0.0 ; shtot(i) = 0.0
1621 if (use_eos .or. .not.cs%linear_drag)
then ;
do k=1,nz
1622 if (htot_vel>=cs%Htbl_shelf)
exit 1623 hweight = min(cs%Htbl_shelf - htot_vel, h_at_vel(i,k))
1624 if (hweight <= 1.5*gv%Angstrom + h_neglect) cycle
1626 htot_vel = htot_vel + h_at_vel(i,k)
1627 hwtot = hwtot + hweight
1629 if (.not.cs%linear_drag)
then 1630 u_at_v =
set_u_at_v(u, h, g, i, j, k, mask_u)
1631 hutot = hutot + hweight * sqrt(v(i,j,k)**2 + &
1632 u_at_v**2 + u_bg_sq)
1635 thtot(i) = thtot(i) + hweight * 0.5 * (tv%T(i,j,k) + tv%T(i,j+1,k))
1636 shtot(i) = shtot(i) + hweight * 0.5 * (tv%S(i,j,k) + tv%S(i,j+1,k))
1640 if (.not.cs%linear_drag)
then ;
if (hwtot > 0.0)
then 1641 ustar(i) = cdrag_sqrt*hutot/hwtot
1643 ustar(i) = cdrag_sqrt*cs%drag_bg_vel
1646 if (use_eos)
then ;
if (hwtot > 0.0)
then 1647 t_eos(i) = thtot(i)/hwtot ; s_eos(i) = shtot(i)/hwtot
1649 t_eos(i) = 0.0 ; s_eos(i) = 0.0
1655 dr_dt, dr_ds, is-g%IsdB+1, ie-is+1, tv%eqn_of_state)
1658 do i=is,ie ;
if (do_i(i))
then 1661 ustarsq = rho0x400_g * ustar(i)**2
1664 thtot(i) = 0.0 ; shtot(i) = 0.0
1666 if (h_at_vel(i,k) <= 0.0) cycle
1667 t_lay = 0.5 * (tv%T(i,j,k) + tv%T(i,j+1,k))
1668 s_lay = 0.5 * (tv%S(i,j,k) + tv%S(i,j+1,k))
1669 oldfn = dr_dt(i)*(t_lay*htot(i) - thtot(i)) + dr_ds(i)*(s_lay*htot(i) - shtot(i))
1670 if (oldfn >= ustarsq)
exit 1672 dfn = (dr_dt(i)*(0.5*(tv%T(i,j,k+1)+tv%T(i,j+1,k+1)) - t_lay) + &
1673 dr_ds(i)*(0.5*(tv%S(i,j,k+1)+tv%S(i,j+1,k+1)) - s_lay)) * &
1674 (h_at_vel(i,k)+htot(i))
1675 if ((oldfn + dfn) <= ustarsq)
then 1678 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn)/dfn)
1681 htot(i) = htot(i) + dh
1682 thtot(i) = thtot(i) + t_lay*dh ; shtot(i) = shtot(i) + s_lay*dh
1684 if ((oldfn < ustarsq) .and. (h_at_vel(i,nz) > 0.0))
then 1685 t_lay = 0.5*(tv%T(i,j,nz) + tv%T(i,j+1,nz))
1686 s_lay = 0.5*(tv%S(i,j,nz) + tv%S(i,j+1,nz))
1687 if (dr_dt(i)*(t_lay*htot(i) - thtot(i)) + &
1688 dr_ds(i)*(s_lay*htot(i) - shtot(i)) < ustarsq) &
1689 htot(i) = htot(i) + h_at_vel(i,nz)
1694 rlay = gv%Rlay(k) ; rlb = gv%Rlay(k+1)
1696 oldfn = rlay*htot(i) - rhtot(i)
1697 if (oldfn >= ustarsq)
exit 1699 dfn = (rlb - rlay)*(h_at_vel(i,k)+htot(i))
1700 if ((oldfn + dfn) <= ustarsq)
then 1703 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn)/dfn)
1706 htot(i) = htot(i) + dh
1707 rhtot = rhtot + rlay*dh
1709 if (gv%Rlay(nz)*htot(i) - rhtot(i) < ustarsq) &
1710 htot(i) = htot(i) + h_at_vel(i,nz)
1717 ustar1 = ustar(i)*m_to_h
1718 h2f2 = (htot(i)*(g%CoriolisBu(i-1,j)+g%CoriolisBu(i,j)) + h_neglect*cs%Omega)**2
1719 visc%tbl_thick_shelf_v(i,j) = max(cs%Htbl_shelf_min, &
1720 ( htot(i)*ustar1 ) / ( 0.5*ustar1 + sqrt((0.5*ustar1)**2 + h2f2 ) ) )
1721 visc%kv_tbl_shelf_v(i,j) = max(cs%KV_TBL_min, &
1722 cdrag_sqrt*ustar(i)*visc%tbl_thick_shelf_v(i,j))
1729 if (
associated(visc%nkml_visc_u) .and.
associated(visc%nkml_visc_v)) &
1730 call uvchksum(
"nkml_visc_[uv]", visc%nkml_visc_u, &
1731 visc%nkml_visc_v, g%HI,haloshift=0)
1733 if (cs%id_nkml_visc_u > 0) &
1734 call post_data(cs%id_nkml_visc_u, visc%nkml_visc_u, cs%diag)
1735 if (cs%id_nkml_visc_v > 0) &
1736 call post_data(cs%id_nkml_visc_v, visc%nkml_visc_v, cs%diag)
1762 logical :: use_kappa_shear, adiabatic, useKPP, useEPBL
1763 logical :: use_CVMix, MLE_use_PBL_MLD
1764 integer :: isd, ied, jsd, jed, nz
1765 character(len=40) :: mdl =
"MOM_set_visc" 1766 isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
1768 call get_param(param_file, mdl,
"ADIABATIC", adiabatic, default=.false., &
1770 use_kappa_shear = .false. ; use_cvmix = .false. ;
1771 usekpp = .false. ; useepbl = .false.
1772 if (.not.adiabatic)
then 1775 call get_param(param_file, mdl,
"USE_KPP", usekpp, &
1776 "If true, turns on the [CVmix] KPP scheme of Large et al., 1984,\n"// &
1777 "to calculate diffusivities and non-local transport in the OBL.", &
1778 default=.false., do_not_log=.true.)
1779 call get_param(param_file, mdl,
"ENERGETICS_SFC_PBL", useepbl, &
1780 "If true, use an implied energetics planetary boundary \n"//&
1781 "layer scheme to determine the diffusivity and viscosity \n"//&
1782 "in the surface boundary layer.", default=.false., do_not_log=.true.)
1785 if (use_kappa_shear .or. usekpp .or. useepbl .or. use_cvmix)
then 1786 allocate(visc%Kd_turb(isd:ied,jsd:jed,nz+1)) ; visc%Kd_turb(:,:,:) = 0.0
1787 allocate(visc%TKE_turb(isd:ied,jsd:jed,nz+1)) ; visc%TKE_turb(:,:,:) = 0.0
1788 allocate(visc%Kv_turb(isd:ied,jsd:jed,nz+1)) ; visc%Kv_turb(:,:,:) = 0.0
1790 vd =
var_desc(
"Kd_turb",
"m2 s-1",
"Turbulent diffusivity at interfaces", &
1791 hor_grid=
'h', z_grid=
'i')
1794 vd =
var_desc(
"TKE_turb",
"m2 s-2",
"Turbulent kinetic energy per unit mass at interfaces", &
1795 hor_grid=
'h', z_grid=
'i')
1797 vd =
var_desc(
"Kv_turb",
"m2 s-1",
"Turbulent viscosity at interfaces", &
1798 hor_grid=
'h', z_grid=
'i')
1803 call get_param(param_file, mdl,
"MLE_USE_PBL_MLD", mle_use_pbl_mld, &
1804 default=.false., do_not_log=.true.)
1805 if (mle_use_pbl_mld)
then 1806 allocate(visc%MLD(isd:ied,jsd:jed)) ; visc%MLD(:,:) = 0.0
1807 vd =
var_desc(
"MLD",
"m",
"Instantaneous active mixing layer depth", &
1808 hor_grid=
'h', z_grid=
'1')
1814 subroutine set_visc_init(Time, G, GV, param_file, diag, visc, CS, OBC)
1815 type(time_type),
target,
intent(in) :: Time
1820 type(
diag_ctrl),
target,
intent(inout) :: diag
1837 real :: Csmag_chan_dflt, smag_const1, TKE_decay_dflt, bulk_Ri_ML_dflt
1838 real :: Kv_background
1839 real :: omega_frac_dflt
1840 integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB, nz, i, j, n
1841 logical :: use_kappa_shear, adiabatic, differential_diffusion, use_omega
1844 #include "version_variable.h" 1845 character(len=40) :: mdl =
"MOM_set_visc" 1847 if (
associated(cs))
then 1848 call mom_error(warning,
"set_visc_init called with an associated "// &
1849 "control structure.")
1856 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = gv%ke
1857 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1864 cs%RiNo_mix = .false.
1865 use_kappa_shear = .false. ; differential_diffusion = .false.
1866 call get_param(param_file, mdl,
"BOTTOMDRAGLAW", cs%bottomdraglaw, &
1867 "If true, the bottom stress is calculated with a drag \n"//&
1868 "law of the form c_drag*|u|*u. The velocity magnitude \n"//&
1869 "may be an assumed value or it may be based on the \n"//&
1870 "actual velocity in the bottommost HBBL, depending on \n"//&
1871 "LINEAR_DRAG.", default=.true.)
1872 call get_param(param_file, mdl,
"CHANNEL_DRAG", cs%Channel_drag, &
1873 "If true, the bottom drag is exerted directly on each \n"//&
1874 "layer proportional to the fraction of the bottom it \n"//&
1875 "overlies.", default=.false.)
1876 call get_param(param_file, mdl,
"LINEAR_DRAG", cs%linear_drag, &
1877 "If LINEAR_DRAG and BOTTOMDRAGLAW are defined the drag \n"//&
1878 "law is cdrag*DRAG_BG_VEL*u.", default=.false.)
1879 call get_param(param_file, mdl,
"ADIABATIC", adiabatic, default=.false., &
1882 call log_param(param_file, mdl,
"ADIABATIC",adiabatic, &
1883 "There are no diapycnal mass fluxes if ADIABATIC is \n"//&
1884 "true. This assumes that KD = KDML = 0.0 and that \n"//&
1885 "there is no buoyancy forcing, but makes the model \n"//&
1886 "faster by eliminating subroutine calls.", default=.false.)
1889 if (.not.adiabatic)
then 1891 cs%RiNo_mix = use_kappa_shear
1892 call get_param(param_file, mdl,
"DOUBLE_DIFFUSION", differential_diffusion, &
1893 "If true, increase diffusivitives for temperature or salt \n"//&
1894 "based on double-diffusive paramaterization from MOM4/KPP.", &
1897 call get_param(param_file, mdl,
"PRANDTL_TURB", visc%Prandtl_turb, &
1898 "The turbulent Prandtl number applied to shear \n"//&
1899 "instability.", units=
"nondim", default=1.0)
1900 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false.)
1902 call get_param(param_file, mdl,
"DYNAMIC_VISCOUS_ML", cs%dynamic_viscous_ML, &
1903 "If true, use a bulk Richardson number criterion to \n"//&
1904 "determine the mixed layer thickness for viscosity.", &
1906 if (cs%dynamic_viscous_ML)
then 1907 call get_param(param_file, mdl,
"BULK_RI_ML", bulk_ri_ml_dflt, default=0.0)
1908 call get_param(param_file, mdl,
"BULK_RI_ML_VISC", cs%bulk_Ri_ML, &
1909 "The efficiency with which mean kinetic energy released \n"//&
1910 "by mechanically forced entrainment of the mixed layer \n"//&
1911 "is converted to turbulent kinetic energy. By default, \n"//&
1912 "BULK_RI_ML_VISC = BULK_RI_ML or 0.", units=
"nondim", &
1913 default=bulk_ri_ml_dflt)
1914 call get_param(param_file, mdl,
"TKE_DECAY", tke_decay_dflt, default=0.0)
1915 call get_param(param_file, mdl,
"TKE_DECAY_VISC", cs%TKE_decay, &
1916 "TKE_DECAY_VISC relates the vertical rate of decay of \n"//&
1917 "the TKE available for mechanical entrainment to the \n"//&
1918 "natural Ekman depth for use in calculating the dynamic \n"//&
1919 "mixed layer viscosity. By default, \n"//&
1920 "TKE_DECAY_VISC = TKE_DECAY or 0.", units=
"nondim", &
1921 default=tke_decay_dflt)
1922 call get_param(param_file, mdl,
"ML_USE_OMEGA", use_omega, &
1923 "If true, use the absolute rotation rate instead of the \n"//&
1924 "vertical component of rotation when setting the decay \n"//&
1925 "scale for turbulence.", default=.false., do_not_log=.true.)
1926 omega_frac_dflt = 0.0
1928 call mom_error(warning,
"ML_USE_OMEGA is depricated; use ML_OMEGA_FRAC=1.0 instead.")
1929 omega_frac_dflt = 1.0
1931 call get_param(param_file, mdl,
"ML_OMEGA_FRAC", cs%omega_frac, &
1932 "When setting the decay scale for turbulence, use this \n"//&
1933 "fraction of the absolute rotation rate blended with the \n"//&
1934 "local value of f, as sqrt((1-of)*f^2 + of*4*omega^2).", &
1935 units=
"nondim", default=omega_frac_dflt)
1936 call get_param(param_file, mdl,
"OMEGA", cs%omega, &
1937 "The rotation rate of the earth.", units=
"s-1", &
1940 cs%ustar_min = 2e-4*cs%omega*(gv%Angstrom_z + gv%H_to_m*gv%H_subroundoff)
1942 call get_param(param_file, mdl,
"OMEGA", cs%omega, &
1943 "The rotation rate of the earth.", units=
"s-1", &
1947 call get_param(param_file, mdl,
"HBBL", cs%Hbbl, &
1948 "The thickness of a bottom boundary layer with a \n"//&
1949 "viscosity of KVBBL if BOTTOMDRAGLAW is not defined, or \n"//&
1950 "the thickness over which near-bottom velocities are \n"//&
1951 "averaged for the drag law if BOTTOMDRAGLAW is defined \n"//&
1952 "but LINEAR_DRAG is not.", units=
"m", fail_if_missing=.true.)
1953 if (cs%bottomdraglaw)
then 1954 call get_param(param_file, mdl,
"CDRAG", cs%cdrag, &
1955 "CDRAG is the drag coefficient relating the magnitude of \n"//&
1956 "the velocity field to the bottom stress. CDRAG is only \n"//&
1957 "used if BOTTOMDRAGLAW is defined.", units=
"nondim", &
1959 call get_param(param_file, mdl,
"DRAG_BG_VEL", cs%drag_bg_vel, &
1960 "DRAG_BG_VEL is either the assumed bottom velocity (with \n"//&
1961 "LINEAR_DRAG) or an unresolved velocity that is \n"//&
1962 "combined with the resolved velocity to estimate the \n"//&
1963 "velocity magnitude. DRAG_BG_VEL is only used when \n"//&
1964 "BOTTOMDRAGLAW is defined.", units=
"m s-1", default=0.0)
1965 call get_param(param_file, mdl,
"BBL_USE_EOS", cs%BBL_use_EOS, &
1966 "If true, use the equation of state in determining the \n"//&
1967 "properties of the bottom boundary layer. Otherwise use \n"//&
1968 "the layer target potential densities.", default=.false.)
1970 call get_param(param_file, mdl,
"BBL_THICK_MIN", cs%BBL_thick_min, &
1971 "The minimum bottom boundary layer thickness that can be \n"//&
1972 "used with BOTTOMDRAGLAW. This might be \n"//&
1973 "Kv / (cdrag * drag_bg_vel) to give Kv as the minimum \n"//&
1974 "near-bottom viscosity.", units=
"m", default=0.0)
1975 call get_param(param_file, mdl,
"HTBL_SHELF_MIN", cs%Htbl_shelf_min, &
1976 "The minimum top boundary layer thickness that can be \n"//&
1977 "used with BOTTOMDRAGLAW. This might be \n"//&
1978 "Kv / (cdrag * drag_bg_vel) to give Kv as the minimum \n"//&
1979 "near-top viscosity.", units=
"m", default=cs%BBL_thick_min)
1980 call get_param(param_file, mdl,
"HTBL_SHELF", cs%Htbl_shelf, &
1981 "The thickness over which near-surface velocities are \n"//&
1982 "averaged for the drag law under an ice shelf. By \n"//&
1983 "default this is the same as HBBL", units=
"m", default=cs%Hbbl)
1985 call get_param(param_file, mdl,
"KV", kv_background, &
1986 "The background kinematic viscosity in the interior. \n"//&
1987 "The molecular value, ~1e-6 m2 s-1, may be used.", &
1988 units=
"m2 s-1", fail_if_missing=.true.)
1989 call get_param(param_file, mdl,
"KV_BBL_MIN", cs%KV_BBL_min, &
1990 "The minimum viscosities in the bottom boundary layer.", &
1991 units=
"m2 s-1", default=kv_background)
1992 call get_param(param_file, mdl,
"KV_TBL_MIN", cs%KV_TBL_min, &
1993 "The minimum viscosities in the top boundary layer.", &
1994 units=
"m2 s-1", default=kv_background)
1996 if (cs%Channel_drag)
then 1997 call get_param(param_file, mdl,
"SMAG_LAP_CONST", smag_const1, default=-1.0)
1999 csmag_chan_dflt = 0.15
2000 if (smag_const1 >= 0.0) csmag_chan_dflt = smag_const1
2002 call get_param(param_file, mdl,
"SMAG_CONST_CHANNEL", cs%c_Smag, &
2003 "The nondimensional Laplacian Smagorinsky constant used \n"//&
2004 "in calculating the channel drag if it is enabled. The \n"//&
2005 "default is to use the same value as SMAG_LAP_CONST if \n"//&
2006 "it is defined, or 0.15 if it is not. The value used is \n"//&
2007 "also 0.15 if the specified value is negative.", &
2008 units=
"nondim", default=csmag_chan_dflt)
2009 if (cs%c_Smag < 0.0) cs%c_Smag = 0.15
2012 if (cs%bottomdraglaw)
then 2013 allocate(visc%bbl_thick_u(isdb:iedb,jsd:jed)) ; visc%bbl_thick_u = 0.0
2014 allocate(visc%kv_bbl_u(isdb:iedb,jsd:jed)) ; visc%kv_bbl_u = 0.0
2015 allocate(visc%bbl_thick_v(isd:ied,jsdb:jedb)) ; visc%bbl_thick_v = 0.0
2016 allocate(visc%kv_bbl_v(isd:ied,jsdb:jedb)) ; visc%kv_bbl_v = 0.0
2017 allocate(visc%ustar_bbl(isd:ied,jsd:jed)) ; visc%ustar_bbl = 0.0
2018 allocate(visc%TKE_bbl(isd:ied,jsd:jed)) ; visc%TKE_bbl = 0.0
2020 cs%id_bbl_thick_u = register_diag_field(
'ocean_model',
'bbl_thick_u', &
2021 diag%axesCu1, time,
'BBL thickness at u points',
'meter')
2022 cs%id_kv_bbl_u = register_diag_field(
'ocean_model',
'kv_bbl_u', diag%axesCu1, &
2023 time,
'BBL viscosity at u points',
'meter2 second-1')
2024 cs%id_bbl_thick_v = register_diag_field(
'ocean_model',
'bbl_thick_v', &
2025 diag%axesCv1, time,
'BBL thickness at v points',
'meter')
2026 cs%id_kv_bbl_v = register_diag_field(
'ocean_model',
'kv_bbl_v', diag%axesCv1, &
2027 time,
'BBL viscosity at v points',
'meter2 second-1')
2029 if (cs%Channel_drag)
then 2030 allocate(visc%Ray_u(isdb:iedb,jsd:jed,nz)) ; visc%Ray_u = 0.0
2031 allocate(visc%Ray_v(isd:ied,jsdb:jedb,nz)) ; visc%Ray_v = 0.0
2032 cs%id_Ray_u = register_diag_field(
'ocean_model',
'Rayleigh_u', diag%axesCuL, &
2033 time,
'Rayleigh drag velocity at u points',
'meter second-1')
2034 cs%id_Ray_v = register_diag_field(
'ocean_model',
'Rayleigh_v', diag%axesCvL, &
2035 time,
'Rayleigh drag velocity at v points',
'meter second-1')
2038 if (differential_diffusion)
then 2039 allocate(visc%Kd_extra_T(isd:ied,jsd:jed,nz+1)) ; visc%Kd_extra_T = 0.0
2040 allocate(visc%Kd_extra_S(isd:ied,jsd:jed,nz+1)) ; visc%Kd_extra_S = 0.0
2043 if (cs%dynamic_viscous_ML)
then 2044 allocate(visc%nkml_visc_u(isdb:iedb,jsd:jed)) ; visc%nkml_visc_u = 0.0
2045 allocate(visc%nkml_visc_v(isd:ied,jsdb:jedb)) ; visc%nkml_visc_v = 0.0
2046 cs%id_nkml_visc_u = register_diag_field(
'ocean_model',
'nkml_visc_u', &
2047 diag%axesCu1, time,
'Number of layers in viscous mixed layer at u points',
'meter')
2048 cs%id_nkml_visc_v = register_diag_field(
'ocean_model',
'nkml_visc_v', &
2049 diag%axesCv1, time,
'Number of layers in viscous mixed layer at v points',
'meter')
2052 cs%Hbbl = cs%Hbbl * gv%m_to_H
2053 cs%BBL_thick_min = cs%BBL_thick_min * gv%m_to_H
2060 if (cs%bottomdraglaw)
then 2061 deallocate(visc%bbl_thick_u) ;
deallocate(visc%bbl_thick_v)
2062 deallocate(visc%kv_bbl_u) ;
deallocate(visc%kv_bbl_v)
2064 if (cs%Channel_drag)
then 2065 deallocate(visc%Ray_u) ;
deallocate(visc%Ray_v)
2067 if (cs%dynamic_viscous_ML)
then 2068 deallocate(visc%nkml_visc_u) ;
deallocate(visc%nkml_visc_v)
2070 if (
associated(visc%Kd_turb))
deallocate(visc%Kd_turb)
2071 if (
associated(visc%TKE_turb))
deallocate(visc%TKE_turb)
2072 if (
associated(visc%Kv_turb))
deallocate(visc%Kv_turb)
2073 if (
associated(visc%ustar_bbl))
deallocate(visc%ustar_bbl)
2074 if (
associated(visc%TKE_bbl))
deallocate(visc%TKE_bbl)
2075 if (
associated(visc%taux_shelf))
deallocate(visc%taux_shelf)
2076 if (
associated(visc%tauy_shelf))
deallocate(visc%tauy_shelf)
2077 if (
associated(visc%tbl_thick_shelf_u))
deallocate(visc%tbl_thick_shelf_u)
2078 if (
associated(visc%tbl_thick_shelf_v))
deallocate(visc%tbl_thick_shelf_v)
2079 if (
associated(visc%kv_tbl_shelf_u))
deallocate(visc%kv_tbl_shelf_u)
2080 if (
associated(visc%kv_tbl_shelf_v))
deallocate(visc%kv_tbl_shelf_v)
integer, parameter, public obc_direction_s
Indicates the boundary is an effective southern boundary.
integer, parameter, public obc_direction_w
Indicates the boundary is an effective western boundary.
type(vardesc) function, public var_desc(name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
Returns a vardesc type whose elements have been filled with the provided fields. The argument name is...
integer, parameter, public obc_direction_n
Indicates the boundary is an effective northern boundary.
This module implements boundary forcing for MOM6.
subroutine, public set_viscous_bbl(u, v, h, tv, visc, G, GV, CS)
The following subroutine calculates the thickness of the bottom boundary layer and the viscosity with...
Interface to CVMix interior shear schemes.
subroutine, public set_visc_register_restarts(HI, GV, param_file, visc, restart_CS)
This subroutine is used to register any fields associated with the vertvisc_type. ...
Ocean grid type. See mom_grid for details.
Calculates density of sea water from T, S and P.
subroutine, public set_visc_init(Time, G, GV, param_file, diag, visc, CS, OBC)
Provides the ocean grid type.
Open boundary segment data structure.
The vertvisc_type structure contains vertical viscosities, drag coefficients, and related fields...
real function set_v_at_u(v, h, G, i, j, k, mask2dCv)
This subroutine finds a thickness-weighted value of v at the u-points.
This module contains I/O framework code.
Defines the horizontal index type (hor_index_type) used for providing index ranges.
subroutine, public set_visc_end(visc, CS)
Container for horizontal index ranges for data, computational and global domains. ...
subroutine, public calculate_density_derivs(T, S, pressure, drho_dT, drho_dS, start, npts, EOS)
Calls the appropriate subroutine to calculate density derivatives for 1-D array inputs.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
subroutine, public set_viscous_ml(u, v, h, tv, fluxes, visc, dt, G, GV, CS)
The following subroutine calculates the thickness of the surface boundary layer for applying an eleva...
Provides subroutines for quantities specific to the equation of state.
integer, parameter, public obc_direction_e
Indicates the boundary is an effective eastern boundary.
Type for describing a variable, typically a tracer.
logical function, public cvmix_shear_is_used(param_file)
Reads the parameters "LMD94" and "PP81" and returns state. This function allows other modules to know...
The thermo_var_ptrs structure contains pointers to an assortment of thermodynamic fields that may be ...
real function set_u_at_v(u, h, G, i, j, k, mask2dCu)
This subroutine finds a thickness-weighted value of u at the v-points.
integer, parameter, public obc_none
Controls where open boundary conditions are applied.
subroutine, public mom_error(level, message, all_print)
logical function, public kappa_shear_is_used(param_file)