8 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, clock_routine
31 implicit none ;
private
33 #include <MOM_memory.h>
56 real :: htbl_shelf_min
59 logical :: bottomdraglaw
64 logical :: bbl_use_eos
66 logical :: linear_drag
67 logical :: channel_drag
71 logical :: dynamic_viscous_ml
84 logical :: answers_2018
92 integer :: id_bbl_thick_u = -1, id_kv_bbl_u = -1
93 integer :: id_bbl_thick_v = -1, id_kv_bbl_v = -1
94 integer :: id_ray_u = -1, id_ray_v = -1
95 integer :: id_nkml_visc_u = -1, id_nkml_visc_v = -1
109 subroutine set_viscous_bbl(u, v, h, tv, visc, G, GV, US, CS, symmetrize)
113 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
115 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
117 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
126 logical,
optional,
intent(in) :: symmetrize
131 real,
dimension(SZIB_(G)) :: &
147 real,
dimension(SZIB_(G),SZJ_(G)) :: &
151 real,
dimension(SZI_(G),SZJB_(G)) :: &
155 real,
dimension(SZIB_(G),SZK_(G)) :: &
199 real :: v_at_u, u_at_v
203 real,
dimension(SZI_(G),SZJ_(G),max(GV%nk_rho_varies,1)) :: &
205 real :: p_ref(szi_(g))
216 real :: apb_4a, ax2_3apb
217 real :: a2x48_apb3, iapb, ibma_2
257 real :: bbl_visc_frac
259 real,
parameter :: c1_3 = 1.0/3.0, c1_6 = 1.0/6.0, c1_12 = 1.0/12.0
262 real :: tmp_val_m1_to_p1
265 logical :: use_l0, do_one_l_iter
266 logical :: use_bbl_eos, do_i(szib_(g))
267 integer :: i, j, k, is, ie, js, je, isq, ieq, jsq, jeq, nz, m, n, k2, nkmb, nkml
268 integer :: itt, maxitt=20
271 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
272 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
273 nkmb = gv%nk_rho_varies ; nkml = gv%nkml
274 h_neglect = gv%H_subroundoff
275 rho0x400_g = 400.0*(gv%Rho0 / (us%L_to_Z**2 * gv%g_Earth)) * gv%Z_to_H
276 vol_quit = 0.9*gv%Angstrom_H + h_neglect
277 c2pi_3 = 8.0*atan(1.0)/3.0
279 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_set_viscosity(BBL): "//&
280 "Module must be initialized before it is used.")
281 if (.not.cs%bottomdraglaw)
return
283 if (
present(symmetrize))
then ;
if (symmetrize)
then
284 jsq = js-1 ; isq = is-1
288 call uvchksum(
"Start set_viscous_BBL [uv]", u, v, g%HI, haloshift=1, scale=us%L_T_to_m_s)
289 call hchksum(h,
"Start set_viscous_BBL h", g%HI, haloshift=1, scale=gv%H_to_m)
290 if (
associated(tv%T))
call hchksum(tv%T,
"Start set_viscous_BBL T", g%HI, haloshift=1)
291 if (
associated(tv%S))
call hchksum(tv%S,
"Start set_viscous_BBL S", g%HI, haloshift=1)
294 use_bbl_eos =
associated(tv%eqn_of_state) .and. cs%BBL_use_EOS
297 u_bg_sq = cs%drag_bg_vel * cs%drag_bg_vel
298 cdrag_sqrt = sqrt(cs%cdrag)
299 cdrag_sqrt_z = us%L_to_Z * sqrt(cs%cdrag)
305 if ((nkml>0) .and. .not.use_bbl_eos)
then
306 do i=isq,ieq+1 ; p_ref(i) = tv%P_ref ;
enddo
308 do j=jsq,jeq+1 ;
do k=1,nkmb
310 rml(:,j,k), isq, ieq-isq+2, tv%eqn_of_state, scale=us%kg_m3_to_R)
315 do j=js-1,je ;
do i=is-1,ie+1
316 d_v(i,j) = 0.5*(g%bathyT(i,j) + g%bathyT(i,j+1))
317 mask_v(i,j) = g%mask2dCv(i,j)
320 do j=js-1,je+1 ;
do i=is-1,ie
321 d_u(i,j) = 0.5*(g%bathyT(i,j) + g%bathyT(i+1,j))
322 mask_u(i,j) = g%mask2dCu(i,j)
325 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
326 if (.not. obc%segment(n)%on_pe) cycle
328 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
329 if (obc%segment(n)%is_N_or_S .and. (j >= js-1) .and. (j <= je))
then
330 do i = max(is-1,obc%segment(n)%HI%isd), min(ie+1,obc%segment(n)%HI%ied)
331 if (obc%segment(n)%direction == obc_direction_n) d_v(i,j) = g%bathyT(i,j)
332 if (obc%segment(n)%direction == obc_direction_s) d_v(i,j) = g%bathyT(i,j+1)
334 elseif (obc%segment(n)%is_E_or_W .and. (i >= is-1) .and. (i <= ie))
then
335 do j = max(js-1,obc%segment(n)%HI%jsd), min(je+1,obc%segment(n)%HI%jed)
336 if (obc%segment(n)%direction == obc_direction_e) d_u(i,j) = g%bathyT(i,j)
337 if (obc%segment(n)%direction == obc_direction_w) d_u(i,j) = g%bathyT(i+1,j)
341 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
344 if (.not. obc%segment(n)%on_pe) cycle
346 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
347 if (obc%segment(n)%is_N_or_S .and. (j >= js-1) .and. (j <= je))
then
348 do i = max(is-1,obc%segment(n)%HI%IsdB), min(ie,obc%segment(n)%HI%IedB)
349 if (obc%segment(n)%direction == obc_direction_n)
then
350 d_u(i,j+1) = d_u(i,j) ; mask_u(i,j+1) = 0.0
351 elseif (obc%segment(n)%direction == obc_direction_s)
then
352 d_u(i,j) = d_u(i,j+1) ; mask_u(i,j) = 0.0
355 elseif (obc%segment(n)%is_E_or_W .and. (i >= is-1) .and. (i <= ie))
then
356 do j = max(js-1,obc%segment(n)%HI%JsdB), min(je,obc%segment(n)%HI%JedB)
357 if (obc%segment(n)%direction == obc_direction_e)
then
358 d_v(i+1,j) = d_v(i,j) ; mask_v(i+1,j) = 0.0
359 elseif (obc%segment(n)%direction == obc_direction_w)
then
360 d_v(i,j) = d_v(i+1,j) ; mask_v(i,j) = 0.0
366 if (.not.use_bbl_eos) rml_vel(:,:) = 0.0
372 do j=jsq,jeq ;
do m=1,2
379 if (g%mask2dCu(i,j) > 0) do_i(i) = .true.
382 is = g%isc ; ie = g%iec
385 if (g%mask2dCv(i,j) > 0) do_i(i) = .true.
390 do k=1,nz ;
do i=is,ie
392 if (u(i,j,k) *(h(i+1,j,k) - h(i,j,k)) >= 0)
then
393 h_at_vel(i,k) = 2.0*h(i,j,k)*h(i+1,j,k) / &
394 (h(i,j,k) + h(i+1,j,k) + h_neglect)
396 h_at_vel(i,k) = 0.5 * (h(i,j,k) + h(i+1,j,k))
399 h_vel(i,k) = 0.5 * (h(i,j,k) + h(i+1,j,k))
401 if (use_bbl_eos)
then ;
do k=1,nz ;
do i=is,ie
403 t_vel(i,k) = 0.5 * (tv%T(i,j,k) + tv%T(i+1,j,k))
404 s_vel(i,k) = 0.5 * (tv%S(i,j,k) + tv%S(i+1,j,k))
405 enddo ;
enddo ;
else ;
do k=1,nkmb ;
do i=is,ie
406 rml_vel(i,k) = 0.5 * (rml(i,j,k) + rml(i+1,j,k))
407 enddo ;
enddo ;
endif
409 do k=1,nz ;
do i=is,ie
411 if (v(i,j,k) * (h(i,j+1,k) - h(i,j,k)) >= 0)
then
412 h_at_vel(i,k) = 2.0*h(i,j,k)*h(i,j+1,k) / &
413 (h(i,j,k) + h(i,j+1,k) + h_neglect)
415 h_at_vel(i,k) = 0.5 * (h(i,j,k) + h(i,j+1,k))
418 h_vel(i,k) = 0.5 * (h(i,j,k) + h(i,j+1,k))
420 if (use_bbl_eos)
then ;
do k=1,nz ;
do i=is,ie
421 t_vel(i,k) = 0.5 * (tv%T(i,j,k) + tv%T(i,j+1,k))
422 s_vel(i,k) = 0.5 * (tv%S(i,j,k) + tv%S(i,j+1,k))
423 enddo ;
enddo ;
else ;
do k=1,nkmb ;
do i=is,ie
424 rml_vel(i,k) = 0.5 * (rml(i,j,k) + rml(i,j+1,k))
425 enddo ;
enddo ;
endif
428 if (
associated(obc))
then ;
if (obc%number_of_segments > 0)
then
431 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_u(i,j) /= obc_none))
then
432 if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e)
then
434 h_at_vel(i,k) = h(i,j,k) ; h_vel(i,k) = h(i,j,k)
436 if (use_bbl_eos)
then
438 t_vel(i,k) = tv%T(i,j,k) ; s_vel(i,k) = tv%S(i,j,k)
442 rml_vel(i,k) = rml(i,j,k)
445 elseif (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_w)
then
447 h_at_vel(i,k) = h(i+1,j,k) ; h_vel(i,k) = h(i+1,j,k)
449 if (use_bbl_eos)
then
451 t_vel(i,k) = tv%T(i+1,j,k) ; s_vel(i,k) = tv%S(i+1,j,k)
455 rml_vel(i,k) = rml(i+1,j,k)
461 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_v(i,j) /= obc_none))
then
462 if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n)
then
464 h_at_vel(i,k) = h(i,j,k) ; h_vel(i,k) = h(i,j,k)
466 if (use_bbl_eos)
then
468 t_vel(i,k) = tv%T(i,j,k) ; s_vel(i,k) = tv%S(i,j,k)
472 rml_vel(i,k) = rml(i,j,k)
475 elseif (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_s)
then
477 h_at_vel(i,k) = h(i,j+1,k) ; h_vel(i,k) = h(i,j+1,k)
479 if (use_bbl_eos)
then
481 t_vel(i,k) = tv%T(i,j+1,k) ; s_vel(i,k) = tv%S(i,j+1,k)
485 rml_vel(i,k) = rml(i,j+1,k)
493 if (use_bbl_eos .or. .not.cs%linear_drag)
then
494 do i=is,ie ;
if (do_i(i))
then
498 htot_vel = 0.0 ; hwtot = 0.0 ; hutot = 0.0
499 thtot = 0.0 ; shtot = 0.0
502 if (htot_vel>=cs%Hbbl)
exit
504 hweight = min(cs%Hbbl - htot_vel, h_at_vel(i,k))
505 if (hweight < 1.5*gv%Angstrom_H + h_neglect) cycle
507 htot_vel = htot_vel + h_at_vel(i,k)
508 hwtot = hwtot + hweight
510 if ((.not.cs%linear_drag) .and. (hweight >= 0.0))
then ;
if (m==1)
then
511 v_at_u =
set_v_at_u(v, h, g, i, j, k, mask_v, obc)
512 hutot = hutot + hweight * sqrt(u(i,j,k)*u(i,j,k) + &
513 v_at_u*v_at_u + u_bg_sq)
515 u_at_v =
set_u_at_v(u, h, g, i, j, k, mask_u, obc)
516 hutot = hutot + hweight * sqrt(v(i,j,k)*v(i,j,k) + &
517 u_at_v*u_at_v + u_bg_sq)
520 if (use_bbl_eos .and. (hweight >= 0.0))
then
521 thtot = thtot + hweight * t_vel(i,k)
522 shtot = shtot + hweight * s_vel(i,k)
526 if (.not.cs%linear_drag .and. (hwtot > 0.0))
then
527 ustar(i) = cdrag_sqrt_z*hutot/hwtot
529 ustar(i) = cdrag_sqrt_z*cs%drag_bg_vel
532 if (use_bbl_eos)
then ;
if (hwtot > 0.0)
then
533 t_eos(i) = thtot/hwtot ; s_eos(i) = shtot/hwtot
535 t_eos(i) = 0.0 ; s_eos(i) = 0.0
539 do i=is,ie ; ustar(i) = cdrag_sqrt_z*cs%drag_bg_vel ;
enddo
542 if (use_bbl_eos)
then
545 if (.not.do_i(i))
then ; t_eos(i) = 0.0 ; s_eos(i) = 0.0 ;
endif
547 do k=1,nz ;
do i=is,ie
548 press(i) = press(i) + gv%H_to_Pa * h_vel(i,k)
551 is-g%IsdB+1, ie-is+1, tv%eqn_of_state, scale=us%kg_m3_to_R)
554 do i=is,ie ;
if (do_i(i))
then
557 ustarsq = rho0x400_g * ustar(i)**2
564 if (use_bbl_eos)
then
565 thtot = 0.0 ; shtot = 0.0 ; oldfn = 0.0
567 if (h_at_vel(i,k) <= 0.0) cycle
569 oldfn = dr_dt(i)*(thtot - t_vel(i,k)*htot) + &
570 dr_ds(i)*(shtot - s_vel(i,k)*htot)
571 if (oldfn >= ustarsq)
exit
573 dfn = (dr_dt(i)*(t_vel(i,k) - t_vel(i,k-1)) + &
574 dr_ds(i)*(s_vel(i,k) - s_vel(i,k-1))) * &
575 (h_at_vel(i,k) + htot)
577 if ((oldfn + dfn) <= ustarsq)
then
580 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn) / (dfn))
584 thtot = thtot + t_vel(i,k)*dh ; shtot = shtot + s_vel(i,k)*dh
586 if ((oldfn < ustarsq) .and. h_at_vel(i,1) > 0.0)
then
588 if (dr_dt(i) * (thtot - t_vel(i,1)*htot) + &
589 dr_ds(i) * (shtot - s_vel(i,1)*htot) < ustarsq) &
590 htot = htot + h_at_vel(i,1)
595 oldfn = rhtot - gv%Rlay(k)*htot
596 dfn = (gv%Rlay(k) - gv%Rlay(k-1))*(h_at_vel(i,k)+htot)
598 if (oldfn >= ustarsq)
then
600 elseif ((oldfn + dfn) <= ustarsq)
then
603 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn) / (dfn))
607 rhtot = rhtot + gv%Rlay(k)*dh
611 oldfn = rhtot - rml_vel(i,k)*htot
612 dfn = (rml_vel(i,k) - rml_vel(i,k-1)) * (h_at_vel(i,k)+htot)
614 if (oldfn >= ustarsq)
then
616 elseif ((oldfn + dfn) <= ustarsq)
then
619 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn) / (dfn))
623 rhtot = rhtot + rml_vel(i,k)*dh
625 if (rhtot - rml_vel(i,1)*htot < ustarsq) htot = htot + h_at_vel(i,1)
627 if (rhtot - gv%Rlay(1)*htot < ustarsq) htot = htot + h_at_vel(i,1)
635 if (m==1)
then ; c2f = g%CoriolisBu(i,j-1) + g%CoriolisBu(i,j)
636 else ; c2f = g%CoriolisBu(i-1,j) + g%CoriolisBu(i,j) ;
endif
638 if (cs%cdrag * u_bg_sq <= 0.0)
then
641 usth = ustar(i)*gv%Z_to_H ; root = sqrt(0.25*usth**2 + (htot*c2f)**2)
642 if (htot*usth <= (cs%BBL_thick_min+h_neglect) * (0.5*usth + root))
then
643 bbl_thick = cs%BBL_thick_min
645 bbl_thick = (htot * usth) / (0.5*usth + root)
648 bbl_thick = htot / (0.5 + sqrt(0.25 + htot*htot*c2f*c2f/ &
649 ((ustar(i)*ustar(i)) * (gv%Z_to_H**2)) ) )
651 if (bbl_thick < cs%BBL_thick_min) bbl_thick = cs%BBL_thick_min
658 if ((bbl_thick > 0.5*cs%Hbbl) .and. (cs%RiNo_mix)) bbl_thick = 0.5*cs%Hbbl
660 if (cs%Channel_drag)
then
666 tmp = g%mask2dCu(i,j+1) * d_u(i,j+1)
667 dp = 2.0 * d_vel * tmp / (d_vel + tmp)
668 tmp = g%mask2dCu(i,j-1) * d_u(i,j-1)
669 dm = 2.0 * d_vel * tmp / (d_vel + tmp)
672 tmp = g%mask2dCv(i+1,j) * d_v(i+1,j)
673 dp = 2.0 * d_vel * tmp / (d_vel + tmp)
674 tmp = g%mask2dCv(i-1,j) * d_v(i-1,j)
675 dm = 2.0 * d_vel * tmp / (d_vel + tmp)
677 if (dm > dp)
then ; tmp = dp ; dp = dm ; dm = tmp ;
endif
680 dp = gv%Z_to_H*dp ; dm = gv%Z_to_H*dm ; d_vel = gv%Z_to_H*d_vel
682 a_3 = (dp + dm - 2.0*d_vel) ; a = 3.0*a_3 ; a_12 = 0.25*a_3
686 if (abs(a) < 1e-2*(slope + cs%BBL_thick_min)) a = 0.0
694 vol_open = d_vel - dm ; vol_2_reg = vol_open
697 vol_open = 0.25*slope*tmp + c1_12*a
698 vol_2_reg = 0.5*tmp**2 * (a - c1_3*slope)
701 c24_a = 24.0/a ; iapb = 1.0/(a+slope)
702 apb_4a = (slope+a)/(4.0*a) ; a2x48_apb3 = (48.0*(a*a))*(iapb**3)
703 ax2_3apb = 2.0*c1_3*a*iapb
704 elseif (a == 0.0)
then
706 if (slope > 0) iapb = 1.0/slope
708 vol_open = d_vel - dm
709 if (slope >= -a)
then
710 iapb = 1.0e30 ;
if (slope+a /= 0.0) iapb = 1.0/(a+slope)
711 vol_direct = 0.0 ; l_direct = 0.0 ; c24_a = 0.0
713 c24_a = 24.0/a ; iapb = 1.0/(a+slope)
714 l_direct = 1.0 + slope/a
715 vol_direct = -c1_6*a*l_direct**3
717 ibma_2 = 2.0 / (slope - a)
720 l(nz+1) = 0.0 ; vol = 0.0 ; vol_err = 0.0 ; bbl_visc_frac = 0.0
725 vol = vol + h_vel(i,k)
726 h_vel_pos = h_vel(i,k) + h_neglect
728 if (vol >= vol_open)
then ; l(k) = 1.0
730 l(k) = sqrt(2.0*vol*iapb)
734 if (vol < vol_2_reg)
then
737 if (a2x48_apb3*vol < 1e-8)
then
739 l0 = sqrt(2.0*vol*iapb) ; l(k) = l0*(1.0 + ax2_3apb*l0)
741 l(k) = apb_4a * (1.0 - &
742 2.0 * cos(c1_3*acos(a2x48_apb3*vol - 1.0) - c2pi_3))
750 tmp_val_m1_to_p1 = 1.0 - c24_a*(vol_open - vol)
751 tmp_val_m1_to_p1 = max(-1., min(1., tmp_val_m1_to_p1))
752 l(k) = 0.5 - cos(c1_3*acos(tmp_val_m1_to_p1) - c2pi_3)
757 if (vol <= vol_direct)
then
759 l(k) = (-0.25*c24_a*vol)**c1_3
767 if (vol_below + vol_err <= vol_direct)
then
768 l0 = l_direct ; vol_0 = vol_direct
770 l0 = l(k+1) ; vol_0 = vol_below + vol_err
776 dv_dl2 = 0.5*(slope+a) - a*l0 ; dvol = (vol-vol_0)
780 do_one_l_iter = .false.
781 if (cs%answers_2018)
then
782 curv_tol = gv%Angstrom_H*dv_dl2**2 &
783 * (0.25 * dv_dl2 * gv%Angstrom_H - a * l0 * dvol)
784 do_one_l_iter = (a * a * dvol**3) < curv_tol
788 use_l0 = (dvol <= 0.)
790 vol_tol = max(0.5 * gv%Angstrom_H + gv%H_subroundoff, 1e-14 * vol)
791 vol_quit = max(0.9 * gv%Angstrom_H + gv%H_subroundoff, 1e-14 * vol)
793 curv_tol = vol_tol * dv_dl2**2 &
794 * (dv_dl2 * vol_tol - 2.0 * a * l0 * dvol)
795 do_one_l_iter = (a * a * dvol**3) < curv_tol
800 vol_err = 0.5*(l(k)*l(k))*(slope + a_3*(3.0-4.0*l(k))) - vol
801 elseif (do_one_l_iter)
then
804 l(k) = sqrt(l0*l0 + dvol / dv_dl2)
805 vol_err = 0.5*(l(k)*l(k))*(slope + a_3*(3.0-4.0*l(k))) - vol
807 if (dv_dl2*(1.0-l0*l0) < dvol + &
808 dv_dl2 * (vol_open - vol)*ibma_2)
then
809 l_max = sqrt(1.0 - (vol_open - vol)*ibma_2)
811 l_max = sqrt(l0*l0 + dvol / dv_dl2)
813 l_min = sqrt(l0*l0 + dvol / (0.5*(slope+a) - a*l_max))
815 vol_err_min = 0.5*(l_min**2)*(slope + a_3*(3.0-4.0*l_min)) - vol
816 vol_err_max = 0.5*(l_max**2)*(slope + a_3*(3.0-4.0*l_max)) - vol
818 if (abs(vol_err_min) <= vol_quit)
then
819 l(k) = l_min ; vol_err = vol_err_min
821 l(k) = sqrt((l_min**2*vol_err_max - l_max**2*vol_err_min) / &
822 (vol_err_max - vol_err_min))
824 vol_err = 0.5*(l(k)*l(k))*(slope + a_3*(3.0-4.0*l(k))) - vol
825 if (abs(vol_err) <= vol_quit)
exit
828 l(k) = l(k) - vol_err / (l(k)* (slope + a - 2.0*a*l(k)))
839 if (l(k) > l(k+1))
then
840 if (vol_below < bbl_thick)
then
841 bbl_frac = (1.0-vol_below/bbl_thick)**2
842 bbl_visc_frac = bbl_visc_frac + bbl_frac*(l(k) - l(k+1))
847 if (m==1)
then ; cell_width = g%dy_Cu(i,j)
848 else ; cell_width = g%dx_Cv(i,j) ;
endif
849 gam = 1.0 - l(k+1)/l(k)
850 rayleigh = us%L_to_Z * cs%cdrag * (l(k)-l(k+1)) * (1.0-bbl_frac) * &
851 (12.0*cs%c_Smag*h_vel_pos) / (12.0*cs%c_Smag*h_vel_pos + &
852 us%L_to_Z*gv%Z_to_H * cs%cdrag * gam*(1.0-gam)*(1.0-1.5*gam) * l(k)**2 * cell_width)
858 if (rayleigh > 0.0)
then
859 v_at_u =
set_v_at_u(v, h, g, i, j, k, mask_v, obc)
860 visc%Ray_u(i,j,k) = rayleigh*sqrt(u(i,j,k)*u(i,j,k) + &
861 v_at_u*v_at_u + u_bg_sq)
862 else ; visc%Ray_u(i,j,k) = 0.0 ;
endif
864 if (rayleigh > 0.0)
then
865 u_at_v =
set_u_at_v(u, h, g, i, j, k, mask_u, obc)
866 visc%Ray_v(i,j,k) = rayleigh*sqrt(v(i,j,k)*v(i,j,k) + &
867 u_at_v*u_at_v + u_bg_sq)
868 else ; visc%Ray_v(i,j,k) = 0.0 ;
endif
873 bbl_thick_z = bbl_thick * gv%H_to_Z
875 visc%Kv_bbl_u(i,j) = max(cs%Kv_BBL_min, &
876 cdrag_sqrt*ustar(i)*bbl_thick_z*bbl_visc_frac)
877 visc%bbl_thick_u(i,j) = bbl_thick_z
879 visc%Kv_bbl_v(i,j) = max(cs%Kv_BBL_min, &
880 cdrag_sqrt*ustar(i)*bbl_thick_z*bbl_visc_frac)
881 visc%bbl_thick_v(i,j) = bbl_thick_z
887 bbl_thick_z = bbl_thick * gv%H_to_Z
889 visc%Kv_bbl_u(i,j) = max(cs%Kv_BBL_min, cdrag_sqrt*ustar(i)*bbl_thick_z)
890 visc%bbl_thick_u(i,j) = bbl_thick_z
892 visc%Kv_bbl_v(i,j) = max(cs%Kv_BBL_min, cdrag_sqrt*ustar(i)*bbl_thick_z)
893 visc%bbl_thick_v(i,j) = bbl_thick_z
900 if (cs%id_bbl_thick_u > 0) &
901 call post_data(cs%id_bbl_thick_u, visc%bbl_thick_u, cs%diag)
902 if (cs%id_kv_bbl_u > 0) &
903 call post_data(cs%id_kv_bbl_u, visc%kv_bbl_u, cs%diag)
904 if (cs%id_bbl_thick_v > 0) &
905 call post_data(cs%id_bbl_thick_v, visc%bbl_thick_v, cs%diag)
906 if (cs%id_kv_bbl_v > 0) &
907 call post_data(cs%id_kv_bbl_v, visc%kv_bbl_v, cs%diag)
908 if (cs%id_Ray_u > 0) &
909 call post_data(cs%id_Ray_u, visc%Ray_u, cs%diag)
910 if (cs%id_Ray_v > 0) &
911 call post_data(cs%id_Ray_v, visc%Ray_v, cs%diag)
914 if (
associated(visc%Ray_u) .and.
associated(visc%Ray_v)) &
915 call uvchksum(
"Ray [uv]", visc%Ray_u, visc%Ray_v, g%HI, haloshift=0, scale=us%Z_to_m)
916 if (
associated(visc%kv_bbl_u) .and.
associated(visc%kv_bbl_v)) &
917 call uvchksum(
"kv_bbl_[uv]", visc%kv_bbl_u, visc%kv_bbl_v, g%HI, haloshift=0, scale=us%Z2_T_to_m2_s)
918 if (
associated(visc%bbl_thick_u) .and.
associated(visc%bbl_thick_v)) &
919 call uvchksum(
"bbl_thick_[uv]", visc%bbl_thick_u, &
920 visc%bbl_thick_v, g%HI, haloshift=0, scale=us%Z_to_m)
926 function set_v_at_u(v, h, G, i, j, k, mask2dCv, OBC)
928 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
930 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
932 integer,
intent(in) :: i
933 integer,
intent(in) :: j
934 integer,
intent(in) :: k
935 real,
dimension(SZI_(G),SZJB_(G)),&
936 intent(in) :: mask2dcv
942 real :: hwt(0:1,-1:0)
944 integer :: i0, j0, i1, j1
946 do j0 = -1,0 ;
do i0 = 0,1 ; i1 = i+i0 ; j1 = j+j0
947 hwt(i0,j0) = (h(i1,j1,k) + h(i1,j1+1,k)) * mask2dcv(i1,j1)
950 if (
associated(obc))
then ;
if (obc%number_of_segments > 0)
then
951 do j0 = -1,0 ;
do i0 = 0,1 ;
if ((obc%segnum_v(i+i0,j+j0) /= obc_none))
then
952 i1 = i+i0 ; j1 = j+j0
953 if (obc%segment(obc%segnum_v(i1,j1))%direction == obc_direction_n)
then
954 hwt(i0,j0) = 2.0 * h(i1,j1,k) * mask2dcv(i1,j1)
955 elseif (obc%segment(obc%segnum_v(i1,j1))%direction == obc_direction_s)
then
956 hwt(i0,j0) = 2.0 * h(i1,j1+1,k) * mask2dcv(i1,j1)
958 endif ;
enddo ;
enddo
961 hwt_tot = (hwt(0,-1) + hwt(1,0)) + (hwt(1,-1) + hwt(0,0))
964 ((hwt(0,0) * v(i,j,k) + hwt(1,-1) * v(i+1,j-1,k)) + &
965 (hwt(1,0) * v(i+1,j,k) + hwt(0,-1) * v(i,j-1,k))) / hwt_tot
970 function set_u_at_v(u, h, G, i, j, k, mask2dCu, OBC)
972 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
974 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
976 integer,
intent(in) :: i
977 integer,
intent(in) :: j
978 integer,
intent(in) :: k
979 real,
dimension(SZIB_(G),SZJ_(G)), &
980 intent(in) :: mask2dcu
986 real :: hwt(-1:0,0:1)
988 integer :: i0, j0, i1, j1
990 do j0 = 0,1 ;
do i0 = -1,0 ; i1 = i+i0 ; j1 = j+j0
991 hwt(i0,j0) = (h(i1,j1,k) + h(i1+1,j1,k)) * mask2dcu(i1,j1)
994 if (
associated(obc))
then ;
if (obc%number_of_segments > 0)
then
995 do j0 = 0,1 ;
do i0 = -1,0 ;
if ((obc%segnum_u(i+i0,j+j0) /= obc_none))
then
996 i1 = i+i0 ; j1 = j+j0
997 if (obc%segment(obc%segnum_u(i1,j1))%direction == obc_direction_e)
then
998 hwt(i0,j0) = 2.0 * h(i1,j1,k) * mask2dcu(i1,j1)
999 elseif (obc%segment(obc%segnum_u(i1,j1))%direction == obc_direction_w)
then
1000 hwt(i0,j0) = 2.0 * h(i1+1,j1,k) * mask2dcu(i1,j1)
1002 endif ;
enddo ;
enddo
1005 hwt_tot = (hwt(-1,0) + hwt(0,1)) + (hwt(0,0) + hwt(-1,1))
1008 ((hwt(0,0) * u(i,j,k) + hwt(-1,1) * u(i-1,j+1,k)) + &
1009 (hwt(-1,0) * u(i-1,j,k) + hwt(0,1) * u(i,j+1,k))) / hwt_tot
1018 subroutine set_viscous_ml(u, v, h, tv, forces, visc, dt, G, GV, US, CS, symmetrize)
1022 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
1024 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1026 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1034 real,
intent(in) :: dt
1037 logical,
optional,
intent(in) :: symmetrize
1042 real,
dimension(SZIB_(G)) :: &
1063 real,
dimension(SZIB_(G),SZJ_(G)) :: &
1066 real,
dimension(SZI_(G),SZJB_(G)) :: &
1069 real :: h_at_vel(szib_(g),szk_(g))
1072 integer :: k_massive(szib_(g))
1109 real :: cdrag_sqrt_z
1133 logical :: use_eos, do_any, do_any_shelf, do_i(szib_(g))
1134 integer :: i, j, k, is, ie, js, je, isq, ieq, jsq, jeq, nz, k2, nkmb, nkml, n
1137 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1138 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
1139 nkmb = gv%nk_rho_varies ; nkml = gv%nkml
1141 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_set_viscosity(visc_ML): "//&
1142 "Module must be initialized before it is used.")
1143 if (.not.(cs%dynamic_viscous_ML .or.
associated(forces%frac_shelf_u) .or. &
1144 associated(forces%frac_shelf_v)) )
return
1146 if (
present(symmetrize))
then ;
if (symmetrize)
then
1147 jsq = js-1 ; isq = is-1
1150 rho0x400_g = 400.0*(gv%Rho0/(us%L_to_Z**2 * gv%g_Earth)) * gv%Z_to_H
1151 u_bg_sq = cs%drag_bg_vel * cs%drag_bg_vel
1152 cdrag_sqrt = sqrt(cs%cdrag)
1153 cdrag_sqrt_z = us%L_to_Z * sqrt(cs%cdrag)
1156 use_eos =
associated(tv%eqn_of_state)
1157 dt_rho0 = dt / gv%H_to_RZ
1158 h_neglect = gv%H_subroundoff
1159 h_tiny = 2.0*gv%Angstrom_H + h_neglect
1160 g_h_rho0 = (gv%g_Earth*gv%H_to_Z) / (gv%Rho0)
1162 if (
associated(forces%frac_shelf_u) .neqv.
associated(forces%frac_shelf_v)) &
1163 call mom_error(fatal,
"set_viscous_ML: one of forces%frac_shelf_u and "//&
1164 "forces%frac_shelf_v is associated, but the other is not.")
1166 if (
associated(forces%frac_shelf_u))
then
1169 call safe_alloc_ptr(visc%tauy_shelf, g%isd, g%ied, g%JsdB, g%JedB)
1170 call safe_alloc_ptr(visc%tbl_thick_shelf_u, g%IsdB, g%IedB, g%jsd, g%jed)
1171 call safe_alloc_ptr(visc%tbl_thick_shelf_v, g%isd, g%ied, g%JsdB, g%JedB)
1172 call safe_alloc_ptr(visc%kv_tbl_shelf_u, g%IsdB, g%IedB, g%jsd, g%jed)
1173 call safe_alloc_ptr(visc%kv_tbl_shelf_v, g%isd, g%ied, g%JsdB, g%JedB)
1174 call safe_alloc_ptr(visc%taux_shelf, g%IsdB, g%IedB, g%jsd, g%jed)
1175 call safe_alloc_ptr(visc%tauy_shelf, g%isd, g%ied, g%JsdB, g%JedB)
1182 do j=js-1,je ;
do i=is-1,ie+1
1183 mask_v(i,j) = g%mask2dCv(i,j)
1186 do j=js-1,je+1 ;
do i=is-1,ie
1187 mask_u(i,j) = g%mask2dCu(i,j)
1190 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
1193 if (.not. obc%segment(n)%on_pe) cycle
1195 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
1196 if (obc%segment(n)%is_N_or_S .and. (j >= js-1) .and. (j <= je))
then
1197 do i = max(is-1,obc%segment(n)%HI%IsdB), min(ie,obc%segment(n)%HI%IedB)
1198 if (obc%segment(n)%direction == obc_direction_n) mask_u(i,j+1) = 0.0
1199 if (obc%segment(n)%direction == obc_direction_s) mask_u(i,j) = 0.0
1201 elseif (obc%segment(n)%is_E_or_W .and. (i >= is-1) .and. (i <= je))
then
1202 do j = max(js-1,obc%segment(n)%HI%JsdB), min(je,obc%segment(n)%HI%JedB)
1203 if (obc%segment(n)%direction == obc_direction_e) mask_v(i+1,j) = 0.0
1204 if (obc%segment(n)%direction == obc_direction_w) mask_v(i,j) = 0.0
1213 if (cs%dynamic_viscous_ML)
then
1217 if (g%mask2dCu(i,j) < 0.5)
then
1218 do_i(i) = .false. ; visc%nkml_visc_u(i,j) = nkml
1220 do_i(i) = .true. ; do_any = .true.
1222 thtot(i) = 0.0 ; shtot(i) = 0.0 ; rhtot(i) = 0.0
1223 uhtot(i) = dt_rho0 * forces%taux(i,j)
1224 vhtot(i) = 0.25 * dt_rho0 * ((forces%tauy(i,j) + forces%tauy(i+1,j-1)) + &
1225 (forces%tauy(i,j-1) + forces%tauy(i+1,j)))
1227 if (cs%omega_frac >= 1.0)
then ; absf = 2.0*cs%omega ;
else
1228 absf = 0.5*(abs(g%CoriolisBu(i,j)) + abs(g%CoriolisBu(i,j-1)))
1229 if (cs%omega_frac > 0.0) &
1230 absf = sqrt(cs%omega_frac*4.0*cs%omega**2 + (1.0-cs%omega_frac)*absf**2)
1232 u_star = max(cs%ustar_min, 0.5 * (forces%ustar(i,j) + forces%ustar(i+1,j)))
1233 idecay_len_tke(i) = ((absf / u_star) * cs%TKE_decay) * gv%H_to_Z
1237 if (do_any)
then ;
do k=1,nz
1240 if (use_eos .and. (k==nkml+1))
then
1243 press(i) = gv%H_to_Pa * htot(i)
1245 i_2hlay = 1.0 / (h(i,j,k2) + h(i+1,j,k2) + h_neglect)
1246 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
1247 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
1250 isq-g%IsdB+1, ieq-isq+1, tv%eqn_of_state, scale=us%kg_m3_to_R)
1253 do i=isq,ieq ;
if (do_i(i))
then
1255 hlay = 0.5*(h(i,j,k) + h(i+1,j,k))
1256 if (hlay > h_tiny)
then
1257 i_2hlay = 1.0 / (h(i,j,k) + h(i+1,j,k))
1258 v_at_u = 0.5 * (h(i,j,k) * (v(i,j,k) + v(i,j-1,k)) + &
1259 h(i+1,j,k) * (v(i+1,j,k) + v(i+1,j-1,k))) * i_2hlay
1260 uh2 = ((uhtot(i) - htot(i)*u(i,j,k))**2 + (vhtot(i) - htot(i)*v_at_u)**2)
1263 t_lay = (h(i,j,k)*tv%T(i,j,k) + h(i+1,j,k)*tv%T(i+1,j,k)) * i_2hlay
1264 s_lay = (h(i,j,k)*tv%S(i,j,k) + h(i+1,j,k)*tv%S(i+1,j,k)) * i_2hlay
1265 ghprime = g_h_rho0 * (dr_dt(i) * (t_lay*htot(i) - thtot(i)) + &
1266 dr_ds(i) * (s_lay*htot(i) - shtot(i)))
1268 ghprime = g_h_rho0 * (gv%Rlay(k)*htot(i) - rhtot(i))
1271 if (ghprime > 0.0)
then
1272 ribulk = cs%bulk_Ri_ML * exp(-htot(i) * idecay_len_tke(i))
1273 if (ribulk * uh2 <= (htot(i)**2) * ghprime)
then
1274 visc%nkml_visc_u(i,j) = real(k_massive(i))
1276 elseif (ribulk * uh2 <= (htot(i) + hlay)**2 * ghprime)
then
1277 visc%nkml_visc_u(i,j) = real(k-1) + &
1278 ( sqrt(ribulk * uh2 / ghprime) - htot(i) ) / hlay
1285 if (do_i(i)) do_any = .true.
1288 if (.not.do_any)
exit
1291 do i=isq,ieq ;
if (do_i(i))
then
1292 htot(i) = htot(i) + 0.5 * (h(i,j,k) + h(i+1,j,k))
1293 uhtot(i) = uhtot(i) + 0.5 * (h(i,j,k) + h(i+1,j,k)) * u(i,j,k)
1294 vhtot(i) = vhtot(i) + 0.25 * (h(i,j,k) * (v(i,j,k) + v(i,j-1,k)) + &
1295 h(i+1,j,k) * (v(i+1,j,k) + v(i+1,j-1,k)))
1297 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))
1298 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))
1300 rhtot(i) = rhtot(i) + 0.5 * (h(i,j,k) + h(i+1,j,k)) * gv%Rlay(k)
1305 if (do_any)
then ;
do i=isq,ieq ;
if (do_i(i))
then
1306 visc%nkml_visc_u(i,j) = k_massive(i)
1307 endif ;
enddo ;
endif
1310 do_any_shelf = .false.
1311 if (
associated(forces%frac_shelf_u))
then
1313 if (forces%frac_shelf_u(i,j)*g%mask2dCu(i,j) == 0.0)
then
1315 visc%tbl_thick_shelf_u(i,j) = 0.0 ; visc%kv_tbl_shelf_u(i,j) = 0.0
1317 do_i(i) = .true. ; do_any_shelf = .true.
1322 if (do_any_shelf)
then
1323 do k=1,nz ;
do i=isq,ieq ;
if (do_i(i))
then
1324 if (u(i,j,k) *(h(i+1,j,k) - h(i,j,k)) >= 0)
then
1325 h_at_vel(i,k) = 2.0*h(i,j,k)*h(i+1,j,k) / &
1326 (h(i,j,k) + h(i+1,j,k) + h_neglect)
1328 h_at_vel(i,k) = 0.5 * (h(i,j,k) + h(i+1,j,k))
1331 h_at_vel(i,k) = 0.0 ; ustar(i) = 0.0
1332 endif ;
enddo ;
enddo
1334 do i=isq,ieq ;
if (do_i(i))
then
1335 htot_vel = 0.0 ; hwtot = 0.0 ; hutot = 0.0
1336 thtot(i) = 0.0 ; shtot(i) = 0.0
1337 if (use_eos .or. .not.cs%linear_drag)
then ;
do k=1,nz
1338 if (htot_vel>=cs%Htbl_shelf)
exit
1339 hweight = min(cs%Htbl_shelf - htot_vel, h_at_vel(i,k))
1340 if (hweight <= 1.5*gv%Angstrom_H + h_neglect) cycle
1342 htot_vel = htot_vel + h_at_vel(i,k)
1343 hwtot = hwtot + hweight
1345 if (.not.cs%linear_drag)
then
1346 v_at_u =
set_v_at_u(v, h, g, i, j, k, mask_v, obc)
1347 hutot = hutot + hweight * sqrt(u(i,j,k)**2 + &
1348 v_at_u**2 + u_bg_sq)
1351 thtot(i) = thtot(i) + hweight * 0.5 * (tv%T(i,j,k) + tv%T(i+1,j,k))
1352 shtot(i) = shtot(i) + hweight * 0.5 * (tv%S(i,j,k) + tv%S(i+1,j,k))
1356 if ((.not.cs%linear_drag) .and. (hwtot > 0.0))
then
1357 ustar(i) = cdrag_sqrt_z * hutot/hwtot
1359 ustar(i) = cdrag_sqrt_z * cs%drag_bg_vel
1362 if (use_eos)
then ;
if (hwtot > 0.0)
then
1363 t_eos(i) = thtot(i)/hwtot ; s_eos(i) = shtot(i)/hwtot
1365 t_eos(i) = 0.0 ; s_eos(i) = 0.0
1371 dr_dt, dr_ds, isq-g%IsdB+1, ieq-isq+1, tv%eqn_of_state, scale=us%kg_m3_to_R)
1374 do i=isq,ieq ;
if (do_i(i))
then
1377 ustarsq = rho0x400_g * ustar(i)**2
1380 thtot(i) = 0.0 ; shtot(i) = 0.0
1382 if (h_at_vel(i,k) <= 0.0) cycle
1383 t_lay = 0.5 * (tv%T(i,j,k) + tv%T(i+1,j,k))
1384 s_lay = 0.5 * (tv%S(i,j,k) + tv%S(i+1,j,k))
1385 oldfn = dr_dt(i)*(t_lay*htot(i) - thtot(i)) + dr_ds(i)*(s_lay*htot(i) - shtot(i))
1386 if (oldfn >= ustarsq)
exit
1388 dfn = (dr_dt(i)*(0.5*(tv%T(i,j,k+1)+tv%T(i+1,j,k+1)) - t_lay) + &
1389 dr_ds(i)*(0.5*(tv%S(i,j,k+1)+tv%S(i+1,j,k+1)) - s_lay)) * &
1390 (h_at_vel(i,k)+htot(i))
1391 if ((oldfn + dfn) <= ustarsq)
then
1394 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn) / (dfn))
1397 htot(i) = htot(i) + dh
1398 thtot(i) = thtot(i) + t_lay*dh ; shtot(i) = shtot(i) + s_lay*dh
1400 if ((oldfn < ustarsq) .and. (h_at_vel(i,nz) > 0.0))
then
1401 t_lay = 0.5*(tv%T(i,j,nz) + tv%T(i+1,j,nz))
1402 s_lay = 0.5*(tv%S(i,j,nz) + tv%S(i+1,j,nz))
1403 if (dr_dt(i)*(t_lay*htot(i) - thtot(i)) + &
1404 dr_ds(i)*(s_lay*htot(i) - shtot(i)) < ustarsq) &
1405 htot(i) = htot(i) + h_at_vel(i,nz)
1410 rlay = gv%Rlay(k) ; rlb = gv%Rlay(k+1)
1412 oldfn = rlay*htot(i) - rhtot(i)
1413 if (oldfn >= ustarsq)
exit
1415 dfn = (rlb - rlay)*(h_at_vel(i,k)+htot(i))
1416 if ((oldfn + dfn) <= ustarsq)
then
1419 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn) / (dfn))
1422 htot(i) = htot(i) + dh
1423 rhtot(i) = rhtot(i) + rlay*dh
1425 if (gv%Rlay(nz)*htot(i) - rhtot(i) < ustarsq) &
1426 htot(i) = htot(i) + h_at_vel(i,nz)
1433 ustar1 = ustar(i)*gv%Z_to_H
1434 h2f2 = (htot(i)*(g%CoriolisBu(i,j-1)+g%CoriolisBu(i,j)) + h_neglect*cs%omega)**2
1435 tbl_thick_z = gv%H_to_Z * max(cs%Htbl_shelf_min, &
1436 ( htot(i)*ustar1 ) / ( 0.5*ustar1 + sqrt((0.5*ustar1)**2 + h2f2 ) ) )
1437 visc%tbl_thick_shelf_u(i,j) = tbl_thick_z
1438 visc%Kv_tbl_shelf_u(i,j) = max(cs%Kv_TBL_min, cdrag_sqrt*ustar(i)*tbl_thick_z)
1448 if (cs%dynamic_viscous_ML)
then
1452 if (g%mask2dCv(i,j) < 0.5)
then
1453 do_i(i) = .false. ; visc%nkml_visc_v(i,j) = nkml
1455 do_i(i) = .true. ; do_any = .true.
1457 thtot(i) = 0.0 ; shtot(i) = 0.0 ; rhtot(i) = 0.0
1458 vhtot(i) = dt_rho0 * forces%tauy(i,j)
1459 uhtot(i) = 0.25 * dt_rho0 * ((forces%taux(i,j) + forces%taux(i-1,j+1)) + &
1460 (forces%taux(i-1,j) + forces%taux(i,j+1)))
1462 if (cs%omega_frac >= 1.0)
then ; absf = 2.0*cs%omega ;
else
1463 absf = 0.5*(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j)))
1464 if (cs%omega_frac > 0.0) &
1465 absf = sqrt(cs%omega_frac*4.0*cs%omega**2 + (1.0-cs%omega_frac)*absf**2)
1468 u_star = max(cs%ustar_min, 0.5 * (forces%ustar(i,j) + forces%ustar(i,j+1)))
1469 idecay_len_tke(i) = ((absf / u_star) * cs%TKE_decay) * gv%H_to_Z
1474 if (do_any)
then ;
do k=1,nz
1477 if (use_eos .and. (k==nkml+1))
then
1480 press(i) = gv%H_to_Pa * htot(i)
1482 i_2hlay = 1.0 / (h(i,j,k2) + h(i,j+1,k2) + h_neglect)
1483 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
1484 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
1487 is-g%IsdB+1, ie-is+1, tv%eqn_of_state, scale=us%kg_m3_to_R)
1490 do i=is,ie ;
if (do_i(i))
then
1492 hlay = 0.5*(h(i,j,k) + h(i,j+1,k))
1493 if (hlay > h_tiny)
then
1494 i_2hlay = 1.0 / (h(i,j,k) + h(i,j+1,k))
1495 u_at_v = 0.5 * (h(i,j,k) * (u(i-1,j,k) + u(i,j,k)) + &
1496 h(i,j+1,k) * (u(i-1,j+1,k) + u(i,j+1,k))) * i_2hlay
1497 uh2 = ((uhtot(i) - htot(i)*u_at_v)**2 + (vhtot(i) - htot(i)*v(i,j,k))**2)
1500 t_lay = (h(i,j,k)*tv%T(i,j,k) + h(i,j+1,k)*tv%T(i,j+1,k)) * i_2hlay
1501 s_lay = (h(i,j,k)*tv%S(i,j,k) + h(i,j+1,k)*tv%S(i,j+1,k)) * i_2hlay
1502 ghprime = g_h_rho0 * (dr_dt(i) * (t_lay*htot(i) - thtot(i)) + &
1503 dr_ds(i) * (s_lay*htot(i) - shtot(i)))
1505 ghprime = g_h_rho0 * (gv%Rlay(k)*htot(i) - rhtot(i))
1508 if (ghprime > 0.0)
then
1509 ribulk = cs%bulk_Ri_ML * exp(-htot(i) * idecay_len_tke(i))
1510 if (ribulk * uh2 <= htot(i)**2 * ghprime)
then
1511 visc%nkml_visc_v(i,j) = real(k_massive(i))
1513 elseif (ribulk * uh2 <= (htot(i) + hlay)**2 * ghprime)
then
1514 visc%nkml_visc_v(i,j) = real(k-1) + &
1515 ( sqrt(ribulk * uh2 / ghprime) - htot(i) ) / hlay
1522 if (do_i(i)) do_any = .true.
1525 if (.not.do_any)
exit
1528 do i=is,ie ;
if (do_i(i))
then
1529 htot(i) = htot(i) + 0.5 * (h(i,j,k) + h(i,j+1,k))
1530 vhtot(i) = vhtot(i) + 0.5 * (h(i,j,k) + h(i,j+1,k)) * v(i,j,k)
1531 uhtot(i) = uhtot(i) + 0.25 * (h(i,j,k) * (u(i-1,j,k) + u(i,j,k)) + &
1532 h(i,j+1,k) * (u(i-1,j+1,k) + u(i,j+1,k)))
1534 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))
1535 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))
1537 rhtot(i) = rhtot(i) + 0.5 * (h(i,j,k) + h(i,j+1,k)) * gv%Rlay(k)
1542 if (do_any)
then ;
do i=is,ie ;
if (do_i(i))
then
1543 visc%nkml_visc_v(i,j) = k_massive(i)
1544 endif ;
enddo ;
endif
1547 do_any_shelf = .false.
1548 if (
associated(forces%frac_shelf_v))
then
1550 if (forces%frac_shelf_v(i,j)*g%mask2dCv(i,j) == 0.0)
then
1552 visc%tbl_thick_shelf_v(i,j) = 0.0 ; visc%kv_tbl_shelf_v(i,j) = 0.0
1554 do_i(i) = .true. ; do_any_shelf = .true.
1559 if (do_any_shelf)
then
1560 do k=1,nz ;
do i=is,ie ;
if (do_i(i))
then
1561 if (v(i,j,k) * (h(i,j+1,k) - h(i,j,k)) >= 0)
then
1562 h_at_vel(i,k) = 2.0*h(i,j,k)*h(i,j+1,k) / &
1563 (h(i,j,k) + h(i,j+1,k) + h_neglect)
1565 h_at_vel(i,k) = 0.5 * (h(i,j,k) + h(i,j+1,k))
1568 h_at_vel(i,k) = 0.0 ; ustar(i) = 0.0
1569 endif ;
enddo ;
enddo
1571 do i=is,ie ;
if (do_i(i))
then
1572 htot_vel = 0.0 ; hwtot = 0.0 ; hutot = 0.0
1573 thtot(i) = 0.0 ; shtot(i) = 0.0
1574 if (use_eos .or. .not.cs%linear_drag)
then ;
do k=1,nz
1575 if (htot_vel>=cs%Htbl_shelf)
exit
1576 hweight = min(cs%Htbl_shelf - htot_vel, h_at_vel(i,k))
1577 if (hweight <= 1.5*gv%Angstrom_H + h_neglect) cycle
1579 htot_vel = htot_vel + h_at_vel(i,k)
1580 hwtot = hwtot + hweight
1582 if (.not.cs%linear_drag)
then
1583 u_at_v =
set_u_at_v(u, h, g, i, j, k, mask_u, obc)
1584 hutot = hutot + hweight * sqrt(v(i,j,k)**2 + &
1585 u_at_v**2 + u_bg_sq)
1588 thtot(i) = thtot(i) + hweight * 0.5 * (tv%T(i,j,k) + tv%T(i,j+1,k))
1589 shtot(i) = shtot(i) + hweight * 0.5 * (tv%S(i,j,k) + tv%S(i,j+1,k))
1593 if (.not.cs%linear_drag)
then ;
if (hwtot > 0.0)
then
1594 ustar(i) = cdrag_sqrt_z * hutot/hwtot
1596 ustar(i) = cdrag_sqrt_z * cs%drag_bg_vel
1599 if (use_eos)
then ;
if (hwtot > 0.0)
then
1600 t_eos(i) = thtot(i)/hwtot ; s_eos(i) = shtot(i)/hwtot
1602 t_eos(i) = 0.0 ; s_eos(i) = 0.0
1608 dr_dt, dr_ds, is-g%IsdB+1, ie-is+1, tv%eqn_of_state, scale=us%kg_m3_to_R)
1611 do i=is,ie ;
if (do_i(i))
then
1614 ustarsq = rho0x400_g * ustar(i)**2
1617 thtot(i) = 0.0 ; shtot(i) = 0.0
1619 if (h_at_vel(i,k) <= 0.0) cycle
1620 t_lay = 0.5 * (tv%T(i,j,k) + tv%T(i,j+1,k))
1621 s_lay = 0.5 * (tv%S(i,j,k) + tv%S(i,j+1,k))
1622 oldfn = dr_dt(i)*(t_lay*htot(i) - thtot(i)) + dr_ds(i)*(s_lay*htot(i) - shtot(i))
1623 if (oldfn >= ustarsq)
exit
1625 dfn = (dr_dt(i)*(0.5*(tv%T(i,j,k+1)+tv%T(i,j+1,k+1)) - t_lay) + &
1626 dr_ds(i)*(0.5*(tv%S(i,j,k+1)+tv%S(i,j+1,k+1)) - s_lay)) * &
1627 (h_at_vel(i,k)+htot(i))
1628 if ((oldfn + dfn) <= ustarsq)
then
1631 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn) / (dfn))
1634 htot(i) = htot(i) + dh
1635 thtot(i) = thtot(i) + t_lay*dh ; shtot(i) = shtot(i) + s_lay*dh
1637 if ((oldfn < ustarsq) .and. (h_at_vel(i,nz) > 0.0))
then
1638 t_lay = 0.5*(tv%T(i,j,nz) + tv%T(i,j+1,nz))
1639 s_lay = 0.5*(tv%S(i,j,nz) + tv%S(i,j+1,nz))
1640 if (dr_dt(i)*(t_lay*htot(i) - thtot(i)) + &
1641 dr_ds(i)*(s_lay*htot(i) - shtot(i)) < ustarsq) &
1642 htot(i) = htot(i) + h_at_vel(i,nz)
1647 rlay = gv%Rlay(k) ; rlb = gv%Rlay(k+1)
1649 oldfn = rlay*htot(i) - rhtot(i)
1650 if (oldfn >= ustarsq)
exit
1652 dfn = (rlb - rlay)*(h_at_vel(i,k)+htot(i))
1653 if ((oldfn + dfn) <= ustarsq)
then
1656 dh = h_at_vel(i,k) * sqrt((ustarsq-oldfn) / (dfn))
1659 htot(i) = htot(i) + dh
1660 rhtot = rhtot + rlay*dh
1662 if (gv%Rlay(nz)*htot(i) - rhtot(i) < ustarsq) &
1663 htot(i) = htot(i) + h_at_vel(i,nz)
1670 ustar1 = ustar(i)*gv%Z_to_H
1671 h2f2 = (htot(i)*(g%CoriolisBu(i-1,j)+g%CoriolisBu(i,j)) + h_neglect*cs%omega)**2
1672 tbl_thick_z = gv%H_to_Z * max(cs%Htbl_shelf_min, &
1673 ( htot(i)*ustar1 ) / ( 0.5*ustar1 + sqrt((0.5*ustar1)**2 + h2f2 ) ) )
1674 visc%tbl_thick_shelf_v(i,j) = tbl_thick_z
1675 visc%Kv_tbl_shelf_v(i,j) = max(cs%Kv_TBL_min, cdrag_sqrt*ustar(i)*tbl_thick_z)
1683 if (
associated(visc%nkml_visc_u) .and.
associated(visc%nkml_visc_v)) &
1684 call uvchksum(
"nkml_visc_[uv]", visc%nkml_visc_u, &
1685 visc%nkml_visc_v, g%HI,haloshift=0)
1687 if (cs%id_nkml_visc_u > 0) &
1688 call post_data(cs%id_nkml_visc_u, visc%nkml_visc_u, cs%diag)
1689 if (cs%id_nkml_visc_v > 0) &
1690 call post_data(cs%id_nkml_visc_v, visc%nkml_visc_v, cs%diag)
1705 logical :: use_kappa_shear, ks_at_vertex
1706 logical :: adiabatic, usekpp, useepbl
1707 logical :: use_cvmix_shear, mle_use_pbl_mld, use_cvmix_conv
1708 integer :: isd, ied, jsd, jed, nz
1710 character(len=40) :: mdl =
"MOM_set_visc"
1711 isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
1713 call get_param(param_file, mdl,
"ADIABATIC", adiabatic, default=.false., &
1716 use_kappa_shear = .false. ; ks_at_vertex = .false. ; use_cvmix_shear = .false.
1717 usekpp = .false. ; useepbl = .false. ; use_cvmix_conv = .false.
1719 if (.not.adiabatic)
then
1724 call get_param(param_file, mdl,
"USE_KPP", usekpp, &
1725 "If true, turns on the [CVMix] KPP scheme of Large et al., 1994, "//&
1726 "to calculate diffusivities and non-local transport in the OBL.", &
1727 default=.false., do_not_log=.true.)
1728 call get_param(param_file, mdl,
"ENERGETICS_SFC_PBL", useepbl, &
1729 "If true, use an implied energetics planetary boundary "//&
1730 "layer scheme to determine the diffusivity and viscosity "//&
1731 "in the surface boundary layer.", default=.false., do_not_log=.true.)
1734 if (use_kappa_shear .or. usekpp .or. useepbl .or. use_cvmix_shear .or. use_cvmix_conv)
then
1737 "Shear-driven turbulent diffusivity at interfaces",
"m2 s-1", z_grid=
'i')
1739 if (usekpp .or. useepbl .or. use_cvmix_shear .or. use_cvmix_conv .or. &
1740 (use_kappa_shear .and. .not.ks_at_vertex ))
then
1743 "Shear-driven turbulent viscosity at interfaces",
"m2 s-1", z_grid=
'i')
1745 if (use_kappa_shear .and. ks_at_vertex)
then
1746 call safe_alloc_ptr(visc%TKE_turb, hi%IsdB, hi%IedB, hi%JsdB, hi%JedB, nz+1)
1747 call safe_alloc_ptr(visc%Kv_shear_Bu, hi%IsdB, hi%IedB, hi%JsdB, hi%JedB, nz+1)
1749 "Shear-driven turbulent viscosity at vertex interfaces",
"m2 s-1", &
1750 hor_grid=
"Bu", z_grid=
'i')
1751 elseif (use_kappa_shear)
then
1761 call get_param(param_file, mdl,
"MLE_USE_PBL_MLD", mle_use_pbl_mld, &
1762 default=.false., do_not_log=.true.)
1764 call get_param(param_file, mdl,
"HFREEZE", hfreeze, &
1765 default=-1.0, do_not_log=.true.)
1767 if (mle_use_pbl_mld)
then
1770 "Instantaneous active mixing layer depth",
"m")
1773 if (hfreeze >= 0.0 .and. .not.mle_use_pbl_mld)
then
1781 subroutine set_visc_init(Time, G, GV, US, param_file, diag, visc, CS, restart_CS, OBC)
1782 type(time_type),
target,
intent(in) :: time
1788 type(
diag_ctrl),
target,
intent(inout) :: diag
1798 real :: csmag_chan_dflt, smag_const1, tke_decay_dflt, bulk_ri_ml_dflt
1799 real :: kv_background
1800 real :: omega_frac_dflt
1805 real :: z2_t_rescale
1807 integer :: i, j, k, is, ie, js, je, n
1808 integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb, nz
1809 logical :: default_2018_answers
1810 logical :: use_kappa_shear, adiabatic, use_omega
1811 logical :: use_cvmix_ddiff, differential_diffusion, use_kpp
1814 # include "version_variable.h"
1815 character(len=40) :: mdl =
"MOM_set_visc"
1817 if (
associated(cs))
then
1818 call mom_error(warning,
"set_visc_init called with an associated "// &
1819 "control structure.")
1826 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
1827 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = gv%ke
1828 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1834 cs%RiNo_mix = .false. ; use_cvmix_ddiff = .false.
1835 differential_diffusion = .false.
1836 call get_param(param_file, mdl,
"DEFAULT_2018_ANSWERS", default_2018_answers, &
1837 "This sets the default value for the various _2018_ANSWERS parameters.", &
1839 call get_param(param_file, mdl,
"SET_VISC_2018_ANSWERS", cs%answers_2018, &
1840 "If true, use the order of arithmetic and expressions that recover the "//&
1841 "answers from the end of 2018. Otherwise, use updated and more robust "//&
1842 "forms of the same expressions.", default=default_2018_answers)
1843 call get_param(param_file, mdl,
"BOTTOMDRAGLAW", cs%bottomdraglaw, &
1844 "If true, the bottom stress is calculated with a drag "//&
1845 "law of the form c_drag*|u|*u. The velocity magnitude "//&
1846 "may be an assumed value or it may be based on the "//&
1847 "actual velocity in the bottommost HBBL, depending on "//&
1848 "LINEAR_DRAG.", default=.true.)
1849 call get_param(param_file, mdl,
"CHANNEL_DRAG", cs%Channel_drag, &
1850 "If true, the bottom drag is exerted directly on each "//&
1851 "layer proportional to the fraction of the bottom it "//&
1852 "overlies.", default=.false.)
1853 call get_param(param_file, mdl,
"LINEAR_DRAG", cs%linear_drag, &
1854 "If LINEAR_DRAG and BOTTOMDRAGLAW are defined the drag "//&
1855 "law is cdrag*DRAG_BG_VEL*u.", default=.false.)
1856 call get_param(param_file, mdl,
"ADIABATIC", adiabatic, default=.false., &
1859 call log_param(param_file, mdl,
"ADIABATIC",adiabatic, &
1860 "There are no diapycnal mass fluxes if ADIABATIC is "//&
1861 "true. This assumes that KD = KDML = 0.0 and that "//&
1862 "there is no buoyancy forcing, but makes the model "//&
1863 "faster by eliminating subroutine calls.", default=.false.)
1866 if (.not.adiabatic)
then
1868 call get_param(param_file, mdl,
"DOUBLE_DIFFUSION", differential_diffusion, &
1869 "If true, increase diffusivites for temperature or salt "//&
1870 "based on double-diffusive parameterization from MOM4/KPP.", &
1875 call get_param(param_file, mdl,
"PRANDTL_TURB", visc%Prandtl_turb, &
1876 "The turbulent Prandtl number applied to shear "//&
1877 "instability.", units=
"nondim", default=1.0)
1878 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false.)
1880 call get_param(param_file, mdl,
"DYNAMIC_VISCOUS_ML", cs%dynamic_viscous_ML, &
1881 "If true, use a bulk Richardson number criterion to "//&
1882 "determine the mixed layer thickness for viscosity.", &
1884 if (cs%dynamic_viscous_ML)
then
1885 call get_param(param_file, mdl,
"BULK_RI_ML", bulk_ri_ml_dflt, default=0.0)
1886 call get_param(param_file, mdl,
"BULK_RI_ML_VISC", cs%bulk_Ri_ML, &
1887 "The efficiency with which mean kinetic energy released "//&
1888 "by mechanically forced entrainment of the mixed layer "//&
1889 "is converted to turbulent kinetic energy. By default, "//&
1890 "BULK_RI_ML_VISC = BULK_RI_ML or 0.", units=
"nondim", &
1891 default=bulk_ri_ml_dflt)
1892 call get_param(param_file, mdl,
"TKE_DECAY", tke_decay_dflt, default=0.0)
1893 call get_param(param_file, mdl,
"TKE_DECAY_VISC", cs%TKE_decay, &
1894 "TKE_DECAY_VISC relates the vertical rate of decay of "//&
1895 "the TKE available for mechanical entrainment to the "//&
1896 "natural Ekman depth for use in calculating the dynamic "//&
1897 "mixed layer viscosity. By default, "//&
1898 "TKE_DECAY_VISC = TKE_DECAY or 0.", units=
"nondim", &
1899 default=tke_decay_dflt)
1900 call get_param(param_file, mdl,
"ML_USE_OMEGA", use_omega, &
1901 "If true, use the absolute rotation rate instead of the "//&
1902 "vertical component of rotation when setting the decay "//&
1903 "scale for turbulence.", default=.false., do_not_log=.true.)
1904 omega_frac_dflt = 0.0
1906 call mom_error(warning,
"ML_USE_OMEGA is depricated; use ML_OMEGA_FRAC=1.0 instead.")
1907 omega_frac_dflt = 1.0
1909 call get_param(param_file, mdl,
"ML_OMEGA_FRAC", cs%omega_frac, &
1910 "When setting the decay scale for turbulence, use this "//&
1911 "fraction of the absolute rotation rate blended with the "//&
1912 "local value of f, as sqrt((1-of)*f^2 + of*4*omega^2).", &
1913 units=
"nondim", default=omega_frac_dflt)
1914 call get_param(param_file, mdl,
"OMEGA", cs%omega, &
1915 "The rotation rate of the earth.", units=
"s-1", &
1916 default=7.2921e-5, scale=us%T_to_s)
1918 cs%ustar_min = 2e-4*cs%omega*(gv%Angstrom_Z + gv%H_to_Z*gv%H_subroundoff)
1920 call get_param(param_file, mdl,
"OMEGA", cs%omega, &
1921 "The rotation rate of the earth.", units=
"s-1", &
1922 default=7.2921e-5, scale=us%T_to_s)
1925 call get_param(param_file, mdl,
"HBBL", cs%Hbbl, &
1926 "The thickness of a bottom boundary layer with a "//&
1927 "viscosity of KVBBL if BOTTOMDRAGLAW is not defined, or "//&
1928 "the thickness over which near-bottom velocities are "//&
1929 "averaged for the drag law if BOTTOMDRAGLAW is defined "//&
1930 "but LINEAR_DRAG is not.", units=
"m", fail_if_missing=.true.)
1931 if (cs%bottomdraglaw)
then
1932 call get_param(param_file, mdl,
"CDRAG", cs%cdrag, &
1933 "CDRAG is the drag coefficient relating the magnitude of "//&
1934 "the velocity field to the bottom stress. CDRAG is only "//&
1935 "used if BOTTOMDRAGLAW is defined.", units=
"nondim", &
1937 call get_param(param_file, mdl,
"DRAG_BG_VEL", cs%drag_bg_vel, &
1938 "DRAG_BG_VEL is either the assumed bottom velocity (with "//&
1939 "LINEAR_DRAG) or an unresolved velocity that is "//&
1940 "combined with the resolved velocity to estimate the "//&
1941 "velocity magnitude. DRAG_BG_VEL is only used when "//&
1942 "BOTTOMDRAGLAW is defined.", units=
"m s-1", default=0.0, scale=us%m_s_to_L_T)
1943 call get_param(param_file, mdl,
"BBL_USE_EOS", cs%BBL_use_EOS, &
1944 "If true, use the equation of state in determining the "//&
1945 "properties of the bottom boundary layer. Otherwise use "//&
1946 "the layer target potential densities.", default=.false.)
1948 call get_param(param_file, mdl,
"BBL_THICK_MIN", cs%BBL_thick_min, &
1949 "The minimum bottom boundary layer thickness that can be "//&
1950 "used with BOTTOMDRAGLAW. This might be "//&
1951 "Kv/(cdrag*drag_bg_vel) to give Kv as the minimum "//&
1952 "near-bottom viscosity.", units=
"m", default=0.0)
1953 call get_param(param_file, mdl,
"HTBL_SHELF_MIN", cs%Htbl_shelf_min, &
1954 "The minimum top boundary layer thickness that can be "//&
1955 "used with BOTTOMDRAGLAW. This might be "//&
1956 "Kv/(cdrag*drag_bg_vel) to give Kv as the minimum "//&
1957 "near-top viscosity.", units=
"m", default=cs%BBL_thick_min, scale=gv%m_to_H)
1958 call get_param(param_file, mdl,
"HTBL_SHELF", cs%Htbl_shelf, &
1959 "The thickness over which near-surface velocities are "//&
1960 "averaged for the drag law under an ice shelf. By "//&
1961 "default this is the same as HBBL", units=
"m", default=cs%Hbbl, scale=gv%m_to_H)
1963 cs%Hbbl = cs%Hbbl * gv%m_to_H
1964 cs%BBL_thick_min = cs%BBL_thick_min * gv%m_to_H
1966 call get_param(param_file, mdl,
"KV", kv_background, &
1967 "The background kinematic viscosity in the interior. "//&
1968 "The molecular value, ~1e-6 m2 s-1, may be used.", &
1969 units=
"m2 s-1", fail_if_missing=.true.)
1971 call get_param(param_file, mdl,
"USE_KPP", use_kpp, &
1972 "If true, turns on the [CVMix] KPP scheme of Large et al., 1994, "//&
1973 "to calculate diffusivities and non-local transport in the OBL.", &
1974 do_not_log=.true., default=.false.)
1976 call get_param(param_file, mdl,
"KV_BBL_MIN", cs%KV_BBL_min, &
1977 "The minimum viscosities in the bottom boundary layer.", &
1978 units=
"m2 s-1", default=kv_background, scale=us%m2_s_to_Z2_T)
1979 call get_param(param_file, mdl,
"KV_TBL_MIN", cs%KV_TBL_min, &
1980 "The minimum viscosities in the top boundary layer.", &
1981 units=
"m2 s-1", default=kv_background, scale=us%m2_s_to_Z2_T)
1983 if (cs%Channel_drag)
then
1984 call get_param(param_file, mdl,
"SMAG_LAP_CONST", smag_const1, default=-1.0)
1986 csmag_chan_dflt = 0.15
1987 if (smag_const1 >= 0.0) csmag_chan_dflt = smag_const1
1989 call get_param(param_file, mdl,
"SMAG_CONST_CHANNEL", cs%c_Smag, &
1990 "The nondimensional Laplacian Smagorinsky constant used "//&
1991 "in calculating the channel drag if it is enabled. The "//&
1992 "default is to use the same value as SMAG_LAP_CONST if "//&
1993 "it is defined, or 0.15 if it is not. The value used is "//&
1994 "also 0.15 if the specified value is negative.", &
1995 units=
"nondim", default=csmag_chan_dflt)
1996 if (cs%c_Smag < 0.0) cs%c_Smag = 0.15
2001 call pass_var(visc%Kv_shear_Bu, g%Domain, position=corner, complete=.true.)
2004 if (cs%bottomdraglaw)
then
2005 allocate(visc%bbl_thick_u(isdb:iedb,jsd:jed)) ; visc%bbl_thick_u = 0.0
2006 allocate(visc%kv_bbl_u(isdb:iedb,jsd:jed)) ; visc%kv_bbl_u = 0.0
2007 allocate(visc%bbl_thick_v(isd:ied,jsdb:jedb)) ; visc%bbl_thick_v = 0.0
2008 allocate(visc%kv_bbl_v(isd:ied,jsdb:jedb)) ; visc%kv_bbl_v = 0.0
2009 allocate(visc%ustar_bbl(isd:ied,jsd:jed)) ; visc%ustar_bbl = 0.0
2010 allocate(visc%TKE_bbl(isd:ied,jsd:jed)) ; visc%TKE_bbl = 0.0
2012 cs%id_bbl_thick_u = register_diag_field(
'ocean_model',
'bbl_thick_u', &
2013 diag%axesCu1, time,
'BBL thickness at u points',
'm', conversion=us%Z_to_m)
2014 cs%id_kv_bbl_u = register_diag_field(
'ocean_model',
'kv_bbl_u', diag%axesCu1, &
2015 time,
'BBL viscosity at u points',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
2016 cs%id_bbl_thick_v = register_diag_field(
'ocean_model',
'bbl_thick_v', &
2017 diag%axesCv1, time,
'BBL thickness at v points',
'm', conversion=us%Z_to_m)
2018 cs%id_kv_bbl_v = register_diag_field(
'ocean_model',
'kv_bbl_v', diag%axesCv1, &
2019 time,
'BBL viscosity at v points',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
2021 if (cs%Channel_drag)
then
2022 allocate(visc%Ray_u(isdb:iedb,jsd:jed,nz)) ; visc%Ray_u = 0.0
2023 allocate(visc%Ray_v(isd:ied,jsdb:jedb,nz)) ; visc%Ray_v = 0.0
2024 cs%id_Ray_u = register_diag_field(
'ocean_model',
'Rayleigh_u', diag%axesCuL, &
2025 time,
'Rayleigh drag velocity at u points',
'm s-1', conversion=us%Z_to_m*us%s_to_T)
2026 cs%id_Ray_v = register_diag_field(
'ocean_model',
'Rayleigh_v', diag%axesCvL, &
2027 time,
'Rayleigh drag velocity at v points',
'm s-1', conversion=us%Z_to_m*us%s_to_T)
2030 if (use_cvmix_ddiff .or. differential_diffusion)
then
2031 allocate(visc%Kd_extra_T(isd:ied,jsd:jed,nz+1)) ; visc%Kd_extra_T = 0.0
2032 allocate(visc%Kd_extra_S(isd:ied,jsd:jed,nz+1)) ; visc%Kd_extra_S = 0.0
2035 if (cs%dynamic_viscous_ML)
then
2036 allocate(visc%nkml_visc_u(isdb:iedb,jsd:jed)) ; visc%nkml_visc_u = 0.0
2037 allocate(visc%nkml_visc_v(isd:ied,jsdb:jedb)) ; visc%nkml_visc_v = 0.0
2038 cs%id_nkml_visc_u = register_diag_field(
'ocean_model',
'nkml_visc_u', &
2039 diag%axesCu1, time,
'Number of layers in viscous mixed layer at u points',
'm')
2040 cs%id_nkml_visc_v = register_diag_field(
'ocean_model',
'nkml_visc_v', &
2041 diag%axesCv1, time,
'Number of layers in viscous mixed layer at v points',
'm')
2050 if ((us%m_to_Z_restart /= 0.0) .and. (us%m_to_Z_restart /= us%m_to_Z)) &
2051 z_rescale = us%m_to_Z / us%m_to_Z_restart
2053 if ((us%s_to_T_restart /= 0.0) .and. (us%s_to_T_restart /= us%s_to_T)) &
2054 i_t_rescale = us%s_to_T_restart / us%s_to_T
2055 z2_t_rescale = z_rescale**2*i_t_rescale
2057 if (z2_t_rescale /= 1.0)
then
2058 if (
associated(visc%Kd_shear))
then ;
if (
query_initialized(visc%Kd_shear,
"Kd_shear", restart_cs))
then
2059 do k=1,nz+1 ;
do j=js,je ;
do i=is,ie
2060 visc%Kd_shear(i,j,k) = z2_t_rescale * visc%Kd_shear(i,j,k)
2061 enddo ;
enddo ;
enddo
2064 if (
associated(visc%Kv_shear))
then ;
if (
query_initialized(visc%Kv_shear,
"Kv_shear", restart_cs))
then
2065 do k=1,nz+1 ;
do j=js,je ;
do i=is,ie
2066 visc%Kv_shear(i,j,k) = z2_t_rescale * visc%Kv_shear(i,j,k)
2067 enddo ;
enddo ;
enddo
2070 if (
associated(visc%Kv_shear_Bu))
then ;
if (
query_initialized(visc%Kv_shear_Bu,
"Kv_shear_Bu", restart_cs))
then
2071 do k=1,nz+1 ;
do j=js-1,je ;
do i=is-1,ie
2072 visc%Kv_shear_Bu(i,j,k) = z2_t_rescale * visc%Kv_shear_Bu(i,j,k)
2073 enddo ;
enddo ;
enddo
2086 if (cs%bottomdraglaw)
then
2087 deallocate(visc%bbl_thick_u) ;
deallocate(visc%bbl_thick_v)
2088 deallocate(visc%kv_bbl_u) ;
deallocate(visc%kv_bbl_v)
2090 if (cs%Channel_drag)
then
2091 deallocate(visc%Ray_u) ;
deallocate(visc%Ray_v)
2093 if (cs%dynamic_viscous_ML)
then
2094 deallocate(visc%nkml_visc_u) ;
deallocate(visc%nkml_visc_v)
2096 if (
associated(visc%Kd_shear))
deallocate(visc%Kd_shear)
2097 if (
associated(visc%Kv_slow))
deallocate(visc%Kv_slow)
2098 if (
associated(visc%TKE_turb))
deallocate(visc%TKE_turb)
2099 if (
associated(visc%Kv_shear))
deallocate(visc%Kv_shear)
2100 if (
associated(visc%Kv_shear_Bu))
deallocate(visc%Kv_shear_Bu)
2101 if (
associated(visc%ustar_bbl))
deallocate(visc%ustar_bbl)
2102 if (
associated(visc%TKE_bbl))
deallocate(visc%TKE_bbl)
2103 if (
associated(visc%taux_shelf))
deallocate(visc%taux_shelf)
2104 if (
associated(visc%tauy_shelf))
deallocate(visc%tauy_shelf)
2105 if (
associated(visc%tbl_thick_shelf_u))
deallocate(visc%tbl_thick_shelf_u)
2106 if (
associated(visc%tbl_thick_shelf_v))
deallocate(visc%tbl_thick_shelf_v)
2107 if (
associated(visc%kv_tbl_shelf_u))
deallocate(visc%kv_tbl_shelf_u)
2108 if (
associated(visc%kv_tbl_shelf_v))
deallocate(visc%kv_tbl_shelf_v)