100 use mom_io, only : read_data, slasher
102 implicit none ;
private 104 #include <MOM_memory.h> 110 logical :: biharmonic
120 logical :: better_bound_kh
124 logical :: better_bound_ah
130 logical :: smagorinsky_kh
132 logical :: smagorinsky_ah
136 logical :: modified_leith
140 logical :: bound_coriolis
143 logical :: use_kh_bg_2d
147 real allocable_,
dimension(NIMEM_,NJMEM_) :: &
167 real allocable_,
dimension(NIMEMB_PTR_,NJMEMB_PTR_) :: &
184 real allocable_,
dimension(NIMEM_,NJMEM_) :: &
187 real allocable_,
dimension(NIMEMB_PTR_,NJMEMB_PTR_) :: &
190 real allocable_,
dimension(NIMEMB_PTR_,NJMEM_) :: &
192 real allocable_,
dimension(NIMEM_,NJMEMB_PTR_) :: &
197 real allocable_,
dimension(NIMEM_,NJMEM_) :: &
203 real allocable_,
dimension(NIMEMB_PTR_,NJMEMB_PTR_) :: &
212 integer :: id_diffu = -1, id_diffv = -1
213 integer :: id_ah_h = -1, id_ah_q = -1
214 integer :: id_kh_h = -1, id_kh_q = -1
215 integer :: id_frictwork = -1, id_frictworkintz = -1
231 subroutine horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, CS, OBC)
234 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
236 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
238 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
241 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
244 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
285 real,
dimension(SZIB_(G),SZJ_(G)) :: &
288 real,
dimension(SZI_(G),SZJB_(G)) :: &
292 real,
dimension(SZI_(G),SZJ_(G)) :: &
299 real,
dimension(SZIB_(G),SZJB_(G)) :: &
306 real,
dimension(SZI_(G),SZJB_(G)) :: &
310 real,
dimension(SZIB_(G),SZJ_(G)) :: &
314 real,
dimension(SZIB_(G),SZJB_(G),SZK_(G)) :: &
318 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
345 real :: visc_bound_rem
352 logical :: rescale_Kh
353 logical :: find_FrictWork
354 logical :: apply_OBC = .false.
355 logical :: use_MEKE_Ku
356 integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
357 integer :: i, j, k, n
359 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
360 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
362 h_neglect = gv%H_subroundoff
363 h_neglect3 = h_neglect**3
365 if (
present(obc))
then ;
if (
associated(obc))
then ;
if (obc%OBC_pe)
then 366 apply_obc = obc%Flather_u_BCs_exist_globally .or. obc%Flather_v_BCs_exist_globally
368 endif ;
endif ;
endif 370 if (.not.
associated(cs))
call mom_error(fatal, &
371 "MOM_hor_visc: Module must be initialized before it is used.")
372 if (.not.(cs%Laplacian .or. cs%biharmonic))
return 374 find_frictwork = (cs%id_FrictWork > 0)
375 if (cs%id_FrictWorkIntz > 0) find_frictwork = .true.
376 if (
associated(meke))
then 377 if (
associated(meke%mom_src)) find_frictwork = .true.
381 if (
associated(varmix))
then 382 rescale_kh = varmix%Resoln_scaled_Kh
383 if (rescale_kh .and. &
384 (.not.
associated(varmix%Res_fn_h) .or. .not.
associated(varmix%Res_fn_q))) &
385 call mom_error(fatal,
"MOM_hor_visc: VarMix%Res_fn_h and " //&
386 "VarMix%Res_fn_q both need to be associated with Resoln_scaled_Kh.")
390 use_meke_ku =
associated(meke%Ku)
417 do j=jsq-1,jeq+2 ;
do i=isq-1,ieq+2
418 sh_xx(i,j) = (cs%DY_dxT(i,j)*(g%IdyCu(i,j) * u(i,j,k) - &
419 g%IdyCu(i-1,j) * u(i-1,j,k)) - &
420 cs%DX_dyT(i,j)*(g%IdxCv(i,j) * v(i,j,k) - &
421 g%IdxCv(i,j-1)*v(i,j-1,k)))
422 div_xx(i,j) = 0.5*((g%dyCu(i,j) * u(i,j,k) * (h(i+1,j,k)+h(i,j,k)) - &
423 g%dyCu(i-1,j) * u(i-1,j,k) * (h(i-1,j,k)+h(i,j,k)) ) + &
424 (g%dxCv(i,j) * v(i,j,k) * (h(i,j,k)+h(i,j+1,k)) - &
425 g%dxCv(i,j-1)*v(i,j-1,k)*(h(i,j,k)+h(i,j-1,k))))*g%IareaT(i,j)/ &
426 (h(i,j,k) + h_neglect)
429 do j=js-2,jeq+1 ;
do i=is-2,ieq+1
430 dvdx(i,j) = cs%DY_dxBu(i,j)*(v(i+1,j,k)*g%IdyCv(i+1,j) - v(i,j,k)*g%IdyCv(i,j))
431 dudy(i,j) = cs%DX_dyBu(i,j)*(u(i,j+1,k)*g%IdxCu(i,j+1) - u(i,j,k)*g%IdxCu(i,j))
439 do j=js-2,je+2 ;
do i=isq-1,ieq+1
440 h_u(i,j) = 0.5 * (h(i,j,k) + h(i+1,j,k))
442 do j=jsq-1,jeq+1 ;
do i=is-2,ie+2
443 h_v(i,j) = 0.5 * (h(i,j,k) + h(i,j+1,k))
448 if (apply_obc)
then ;
do n=1,obc%number_of_segments
449 j = obc%segment(n)%HI%JsdB ; i = obc%segment(n)%HI%IsdB
450 if (obc%zero_strain .or. obc%freeslip_strain)
then 451 if (obc%segment(n)%is_N_or_S .and. (j >= js-2) .and. (j <= jeq+1))
then 452 do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
453 if (obc%zero_strain)
then 454 dvdx(i,j) = 0. ; dudy(i,j) = 0.
455 elseif (obc%freeslip_strain)
then 459 elseif (obc%segment(n)%is_E_or_W .and. (i >= is-2) .and. (i <= ieq+1))
then 460 do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
461 if (obc%zero_strain)
then 462 dvdx(i,j) = 0. ; dudy(i,j) = 0.
463 elseif (obc%freeslip_strain)
then 474 if ((j >= jsq-1) .and. (j <= jeq+1))
then 475 do i = max(is-2,obc%segment(n)%HI%isd), min(ie+2,obc%segment(n)%HI%ied)
480 if ((j >= jsq-1) .and. (j <= jeq+1))
then 481 do i = max(is-2,obc%segment(n)%HI%isd), min(ie+2,obc%segment(n)%HI%ied)
482 h_v(i,j) = h(i,j+1,k)
485 elseif (obc%segment(n)%direction == obc_direction_e)
then 486 if ((i >= isq-1) .and. (i <= ieq+1))
then 487 do j = max(js-2,obc%segment(n)%HI%jsd), min(je+2,obc%segment(n)%HI%jed)
491 elseif (obc%segment(n)%direction == obc_direction_w)
then 492 if ((i >= isq-1) .and. (i <= ieq+1))
then 493 do j = max(js-2,obc%segment(n)%HI%jsd), min(je+2,obc%segment(n)%HI%jed)
494 h_u(i,j) = h(i+1,j,k)
500 if (apply_obc)
then ;
do n=1,obc%number_of_segments
501 j = obc%segment(n)%HI%JsdB ; i = obc%segment(n)%HI%IsdB
503 if ((j >= js-2) .and. (j <= je))
then 504 do i = max(isq-1,obc%segment(n)%HI%IsdB), min(ieq+1,obc%segment(n)%HI%IedB)
505 h_u(i,j+1) = h_u(i,j)
509 if ((j >= js-1) .and. (j <= je+1))
then 510 do i = max(isq-1,obc%segment(n)%HI%isd), min(ieq+1,obc%segment(n)%HI%ied)
511 h_u(i,j) = h_u(i,j+1)
514 elseif (obc%segment(n)%direction == obc_direction_e)
then 515 if ((i >= is-2) .and. (i <= ie))
then 516 do j = max(jsq-1,obc%segment(n)%HI%jsd), min(jeq+1,obc%segment(n)%HI%jed)
517 h_v(i+1,j) = h_v(i,j)
520 elseif (obc%segment(n)%direction == obc_direction_w)
then 521 if ((i >= is-1) .and. (i <= ie+1))
then 522 do j = max(jsq-1,obc%segment(n)%HI%jsd), min(jeq+1,obc%segment(n)%HI%jed)
523 h_v(i,j) = h_v(i+1,j)
530 do j=js-2,jeq+1 ;
do i=is-2,ieq+1
531 sh_xy(i,j) = (2.0-g%mask2dBu(i,j)) * ( dvdx(i,j) + dudy(i,j) )
534 do j=js-2,jeq+1 ;
do i=is-2,ieq+1
535 sh_xy(i,j) = g%mask2dBu(i,j) * ( dvdx(i,j) + dudy(i,j) )
540 do j=js-2,jeq+1 ;
do i=is-2,ieq+1
541 vort_xy(i,j) = (2.0-g%mask2dBu(i,j)) * ( dvdx(i,j) - dudy(i,j) )
544 do j=js-2,jeq+1 ;
do i=is-2,ieq+1
545 vort_xy(i,j) = g%mask2dBu(i,j) * ( dvdx(i,j) - dudy(i,j) )
550 do j=js-2,jeq+1 ;
do i=is-1,ieq+1
551 vort_xy_dx(i,j) = cs%DY_dxBu(i,j)*(vort_xy(i,j)*g%IdyCu(i,j) - vort_xy(i-1,j)*g%IdyCu(i-1,j))
554 do j=js-1,jeq+1 ;
do i=is-2,ieq+1
555 vort_xy_dy(i,j) = cs%DX_dyBu(i,j)*(vort_xy(i,j)*g%IdxCv(i,j) - vort_xy(i,j-1)*g%IdxCv(i,j-1))
559 do j=jsq-1,jeq+2 ;
do i=is-2,ieq+1
560 div_xx_dx(i,j) = g%IdxCu(i,j)*(div_xx(i+1,j) - div_xx(i,j))
563 do j=js-2,jeq+1 ;
do i=isq-1,ieq+2
564 div_xx_dy(i,j) = g%IdyCv(i,j)*(div_xx(i,j+1) - div_xx(i,j))
568 if (cs%Modified_Leith)
then 575 if (cs%biharmonic)
then 576 do j=js-1,jeq+1 ;
do i=isq-1,ieq+1
577 u0(i,j) = cs%IDXDY2u(i,j)*(cs%DY2h(i+1,j)*sh_xx(i+1,j) - cs%DY2h(i,j)*sh_xx(i,j)) + &
578 cs%IDX2dyCu(i,j)*(cs%DX2q(i,j)*sh_xy(i,j) - cs%DX2q(i,j-1)*sh_xy(i,j-1))
580 do j=jsq-1,jeq+1 ;
do i=is-1,ieq+1
581 v0(i,j) = cs%IDXDY2v(i,j)*(cs%DY2q(i,j)*sh_xy(i,j) - cs%DY2q(i-1,j)*sh_xy(i-1,j)) - &
582 cs%IDX2dyCv(i,j)*(cs%DX2h(i,j+1)*sh_xx(i,j+1) - cs%DX2h(i,j)*sh_xx(i,j))
584 if (apply_obc .and. obc%zero_biharmonic)
then 585 do n=1,obc%number_of_segments
586 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
587 if (obc%segment(n)%is_N_or_S .and. (j >= jsq-1) .and. (j <= jeq+1))
then 588 do i=obc%segment(n)%HI%isd,obc%segment(n)%HI%ied
591 elseif (obc%segment(n)%is_E_or_W .and. (i >= isq-1) .and. (i <= ieq+1))
then 592 do j=obc%segment(n)%HI%jsd,obc%segment(n)%HI%jed
600 do j=jsq,jeq+1 ;
do i=isq,ieq+1
601 if ((cs%Smagorinsky_Kh) .or. (cs%Smagorinsky_Ah))
then 602 shear_mag = sqrt(sh_xx(i,j)*sh_xx(i,j) + &
603 0.25*((sh_xy(i-1,j-1)*sh_xy(i-1,j-1) + sh_xy(i,j)*sh_xy(i,j)) + &
604 (sh_xy(i-1,j)*sh_xy(i-1,j) + sh_xy(i,j-1)*sh_xy(i,j-1))))
606 if ((cs%Leith_Kh) .or. (cs%Leith_Ah))
then 608 0.5*((vort_xy_dx(i,j-1)*vort_xy_dx(i,j-1) + vort_xy_dx(i,j)*vort_xy_dx(i,j)) + &
609 (vort_xy_dy(i-1,j)*vort_xy_dy(i-1,j) + vort_xy_dy(i,j)*vort_xy_dy(i,j))) + &
610 mod_leith*0.5*((div_xx_dx(i,j)*div_xx_dx(i,j) + div_xx_dx(i-1,j)*div_xx_dx(i-1,j)) + &
611 (div_xx_dy(i,j)*div_xx_dy(i,j) + div_xx_dy(i,j-1)*div_xx_dy(i,j-1))))
613 if (cs%better_bound_Ah .or. cs%better_bound_Kh)
then 614 hrat_min = min(1.0, min(h_u(i,j), h_u(i-1,j), h_v(i,j), h_v(i,j-1)) / &
615 (h(i,j,k) + h_neglect) )
619 if (cs%Laplacian)
then 622 kh_scale = 1.0 ;
if (rescale_kh) kh_scale = varmix%Res_fn_h(i,j)
623 khsm = 0.0; khlth = 0.0
624 if ((cs%Smagorinsky_Kh) .or. (cs%Leith_Kh))
then 625 if (cs%Smagorinsky_Kh) &
626 khsm = cs%LAPLAC_CONST_xx(i,j) * shear_mag
628 khlth = cs%LAPLAC3_CONST_xx(i,j) * vort_mag
629 kh = kh_scale * max(khlth, max(cs%Kh_bg_xx(i,j), khsm))
630 if (cs%bound_Kh .and. .not.cs%better_bound_Kh) &
631 kh = min(kh, cs%Kh_Max_xx(i,j))
633 kh = kh_scale * cs%Kh_bg_xx(i,j)
636 if (use_meke_ku)
then 637 kh = kh + meke%Ku(i,j)
639 if (cs%better_bound_Kh)
then 640 if (kh >= hrat_min*cs%Kh_Max_xx(i,j))
then 642 kh = hrat_min*cs%Kh_Max_xx(i,j)
645 visc_bound_rem = 1.0 - kh / (hrat_min*cs%Kh_Max_xx(i,j))
649 if (cs%id_Kh_h>0) kh_h(i,j,k) = kh
651 str_xx(i,j) = -kh * sh_xx(i,j)
656 if (cs%biharmonic)
then 659 ahsm = 0.0; ahlth = 0.0
660 if ((cs%Smagorinsky_Ah) .or. (cs%Leith_Ah))
then 661 if (cs%Smagorinsky_Ah)
then 662 if (cs%bound_Coriolis)
then 663 ahsm = shear_mag * (cs%BIHARM_CONST_xx(i,j) + &
664 cs%Biharm_Const2_xx(i,j)*shear_mag)
666 ahsm = cs%BIHARM_CONST_xx(i,j) * shear_mag
670 ahlth = vort_mag * (cs%BIHARM_CONST_xx(i,j))
671 ah = max(max(cs%Ah_bg_xx(i,j), ahsm),ahlth)
672 if (cs%bound_Ah .and. .not.cs%better_bound_Ah) &
673 ah = min(ah, cs%Ah_Max_xx(i,j))
675 ah = cs%Ah_bg_xx(i,j)
678 if (cs%better_bound_Ah)
then 679 ah = min(ah, visc_bound_rem*hrat_min*cs%Ah_Max_xx(i,j))
682 if (cs%id_Ah_h>0) ah_h(i,j,k) = ah
684 str_xx(i,j) = str_xx(i,j) + ah * &
685 (cs%DY_dxT(i,j)*(g%IdyCu(i,j)*u0(i,j) - g%IdyCu(i-1,j)*u0(i-1,j)) - &
686 cs%DX_dyT(i,j) *(g%IdxCv(i,j)*v0(i,j) - g%IdxCv(i,j-1)*v0(i,j-1)))
689 bhstr_xx(i,j) = ah * &
690 (cs%DY_dxT(i,j)*(g%IdyCu(i,j)*u0(i,j) - g%IdyCu(i-1,j)*u0(i-1,j)) - &
691 cs%DX_dyT(i,j) *(g%IdxCv(i,j)*v0(i,j) - g%IdxCv(i,j-1)*v0(i,j-1)))
692 bhstr_xx(i,j) = bhstr_xx(i,j) * (h(i,j,k) * cs%reduction_xx(i,j))
696 str_xx(i,j) = str_xx(i,j) * (h(i,j,k) * cs%reduction_xx(i,j))
699 if (cs%biharmonic)
then 701 do j=js-1,jeq ;
do i=is-1,ieq
702 dvdx(i,j) = cs%DY_dxBu(i,j)*(v0(i+1,j)*g%IdyCv(i+1,j) - v0(i,j)*g%IdyCv(i,j))
703 dudy(i,j) = cs%DX_dyBu(i,j)*(u0(i,j+1)*g%IdxCu(i,j+1) - u0(i,j)*g%IdxCu(i,j))
706 if (apply_obc)
then ;
if (obc%zero_strain .or. obc%freeslip_strain)
then 707 do n=1,obc%number_of_segments
708 j = obc%segment(n)%HI%JsdB ; i = obc%segment(n)%HI%IsdB
709 if (obc%segment(n)%is_N_or_S .and. (j >= js-1) .and. (j <= jeq))
then 710 do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
711 if (obc%zero_strain)
then 712 dvdx(i,j) = 0. ; dudy(i,j) = 0.
713 elseif (obc%freeslip_strain)
then 717 elseif (obc%segment(n)%is_E_or_W .and. (i >= is-1) .and. (i <= ieq))
then 718 do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
719 if (obc%zero_strain)
then 720 dvdx(i,j) = 0. ; dudy(i,j) = 0.
721 elseif (obc%freeslip_strain)
then 730 do j=js-1,jeq ;
do i=is-1,ieq
731 if ((cs%Smagorinsky_Kh) .or. (cs%Smagorinsky_Ah))
then 732 shear_mag = sqrt(sh_xy(i,j)*sh_xy(i,j) + &
733 0.25*((sh_xx(i,j)*sh_xx(i,j) + sh_xx(i+1,j+1)*sh_xx(i+1,j+1)) + &
734 (sh_xx(i,j+1)*sh_xx(i,j+1) + sh_xx(i+1,j)*sh_xx(i+1,j))))
736 if ((cs%Leith_Kh) .or. (cs%Leith_Ah)) &
738 0.5*((vort_xy_dx(i,j)*vort_xy_dx(i,j) + vort_xy_dx(i+1,j)*vort_xy_dx(i+1,j)) + &
739 (vort_xy_dy(i,j)*vort_xy_dy(i,j) + vort_xy_dy(i,j+1)*vort_xy_dy(i,j+1))) + &
740 mod_leith*0.5*((div_xx_dx(i,j)*div_xx_dx(i,j) + div_xx_dx(i,j+1)*div_xx_dx(i,j+1)) + &
741 (div_xx_dy(i,j)*div_xx_dy(i,j) + div_xx_dy(i+1,j)*div_xx_dy(i+1,j))))
743 h2uq = 4.0 * h_u(i,j) * h_u(i,j+1)
744 h2vq = 4.0 * h_v(i,j) * h_v(i+1,j)
747 hq = 2.0 * h2uq * h2vq / (h_neglect3 + (h2uq + h2vq) * &
748 ((h_u(i,j) + h_u(i,j+1)) + (h_v(i,j) + h_v(i+1,j))))
750 if (cs%better_bound_Ah .or. cs%better_bound_Kh)
then 751 hrat_min = min(1.0, min(h_u(i,j), h_u(i,j+1), h_v(i,j), h_v(i+1,j)) / &
756 if (cs%no_slip .and. (g%mask2dBu(i,j) < 0.5))
then 757 if ((g%mask2dCu(i,j) + g%mask2dCu(i,j+1)) + &
758 (g%mask2dCv(i,j) + g%mask2dCv(i+1,j)) > 0.0)
then 761 hu = g%mask2dCu(i,j) * h_u(i,j) + g%mask2dCu(i,j+1) * h_u(i,j+1)
762 hv = g%mask2dCv(i,j) * h_v(i,j) + g%mask2dCv(i+1,j) * h_v(i+1,j)
763 if ((g%mask2dCu(i,j) + g%mask2dCu(i,j+1)) * &
764 (g%mask2dCv(i,j) + g%mask2dCv(i+1,j)) == 0.0)
then 770 hq = 2.0 * (hu * hv) / ((hu + hv) + h_neglect)
771 hrat_min = min(1.0, min(hu, hv) / (hq + h_neglect) )
776 if (cs%Laplacian)
then 779 kh_scale = 1.0 ;
if (rescale_kh) kh_scale = varmix%Res_fn_q(i,j)
780 khsm = 0.0; khlth = 0.0
781 if ((cs%Smagorinsky_Kh) .or. (cs%Leith_Kh))
then 782 if (cs%Smagorinsky_Kh) &
783 khsm = cs%LAPLAC_CONST_xy(i,j) * shear_mag
785 khlth = cs%LAPLAC3_CONST_xy(i,j) * vort_mag
786 kh = kh_scale * max(max(cs%Kh_bg_xy(i,j), khsm), khlth)
787 if (cs%bound_Kh .and. .not.cs%better_bound_Kh) &
788 kh = min(kh, cs%Kh_Max_xy(i,j))
790 kh = kh_scale * cs%Kh_bg_xy(i,j)
792 if (use_meke_ku)
then 793 kh = kh + 0.25*( (meke%Ku(i,j)+meke%Ku(i+1,j+1)) &
794 +(meke%Ku(i+1,j)+meke%Ku(i,j+1)) )
797 kh = max(kh,cs%Kh_bg_min)
799 if (cs%better_bound_Kh)
then 800 if (kh >= hrat_min*cs%Kh_Max_xy(i,j))
then 802 kh = hrat_min*cs%Kh_Max_xy(i,j)
803 elseif (cs%Kh_Max_xy(i,j)>0.)
then 805 visc_bound_rem = 1.0 - kh / (hrat_min*cs%Kh_Max_xy(i,j))
809 if (cs%id_Kh_q>0) kh_q(i,j,k) = kh
811 str_xy(i,j) = -kh * sh_xy(i,j)
816 if (cs%biharmonic)
then 819 ahsm = 0.0; ahlth = 0.0
820 if (cs%Smagorinsky_Ah .or. cs%Leith_Ah)
then 821 if (cs%Smagorinsky_Ah)
then 822 if (cs%bound_Coriolis)
then 823 ahsm = shear_mag * (cs%BIHARM_CONST_xy(i,j) + &
824 cs%Biharm_Const2_xy(i,j)*shear_mag)
826 ahsm = cs%BIHARM_CONST_xy(i,j) * shear_mag
830 ahlth = vort_mag * (cs%BIHARM5_CONST_xy(i,j))
831 ah = max(max(cs%Ah_bg_xy(i,j), ahsm),ahlth)
832 if (cs%bound_Ah .and. .not.cs%better_bound_Ah) &
833 ah = min(ah, cs%Ah_Max_xy(i,j))
835 ah = cs%Ah_bg_xy(i,j)
837 if (cs%better_bound_Ah)
then 838 ah = min(ah, visc_bound_rem*hrat_min*cs%Ah_Max_xy(i,j))
841 if (cs%id_Ah_q>0) ah_q(i,j,k) = ah
843 str_xy(i,j) = str_xy(i,j) + ah * ( dvdx(i,j) + dudy(i,j) )
846 bhstr_xy(i,j) = ah * ( dvdx(i,j) + dudy(i,j) ) * &
847 (hq * g%mask2dBu(i,j) * cs%reduction_xy(i,j))
852 str_xy(i,j) = str_xy(i,j) * (hq * cs%reduction_xy(i,j))
854 str_xy(i,j) = str_xy(i,j) * (hq * g%mask2dBu(i,j) * cs%reduction_xy(i,j))
858 do j=js,je ;
do i=isq,ieq
860 diffu(i,j,k) = ((g%IdyCu(i,j)*(cs%DY2h(i,j) *str_xx(i,j) - &
861 cs%DY2h(i+1,j)*str_xx(i+1,j)) + &
862 g%IdxCu(i,j)*(cs%DX2q(i,j-1)*str_xy(i,j-1) - &
863 cs%DX2q(i,j) *str_xy(i,j))) * &
864 g%IareaCu(i,j)) / (h_u(i,j) + h_neglect)
870 do n=1,obc%number_of_segments
871 if (obc%segment(n)%is_E_or_W)
then 872 i = obc%segment(n)%HI%IsdB
873 do j=obc%segment(n)%HI%jsd,obc%segment(n)%HI%jed
881 do j=jsq,jeq ;
do i=is,ie
882 diffv(i,j,k) = ((g%IdyCv(i,j)*(cs%DY2q(i-1,j)*str_xy(i-1,j) - &
883 cs%DY2q(i,j) *str_xy(i,j)) - &
884 g%IdxCv(i,j)*(cs%DX2h(i,j) *str_xx(i,j) - &
885 cs%DX2h(i,j+1)*str_xx(i,j+1))) * &
886 g%IareaCv(i,j)) / (h_v(i,j) + h_neglect)
891 do n=1,obc%number_of_segments
892 if (obc%segment(n)%is_N_or_S)
then 893 j = obc%segment(n)%HI%JsdB
894 do i=obc%segment(n)%HI%isd,obc%segment(n)%HI%ied
901 if (find_frictwork)
then ;
do j=js,je ;
do i=is,ie
903 frictwork(i,j,k) = gv%H_to_kg_m2 * ( &
904 (str_xx(i,j)*(u(i,j,k)-u(i-1,j,k))*g%IdxT(i,j) &
905 -str_xx(i,j)*(v(i,j,k)-v(i,j-1,k))*g%IdyT(i,j)) &
906 +0.25*((str_xy(i,j)*( &
907 (u(i,j+1,k)-u(i,j,k))*g%IdyBu(i,j) &
908 +(v(i+1,j,k)-v(i,j,k))*g%IdxBu(i,j) ) &
910 (u(i-1,j,k)-u(i-1,j-1,k))*g%IdyBu(i-1,j-1) &
911 +(v(i,j-1,k)-v(i-1,j-1,k))*g%IdxBu(i-1,j-1) )) &
913 (u(i-1,j+1,k)-u(i-1,j,k))*g%IdyBu(i-1,j) &
914 +(v(i,j,k)-v(i-1,j,k))*g%IdxBu(i-1,j) ) &
916 (u(i,j,k)-u(i,j-1,k))*g%IdyBu(i,j-1) &
917 +(v(i+1,j-1,k)-v(i,j-1,k))*g%IdxBu(i,j-1) )) ) )
918 enddo ;
enddo ;
endif 923 if (find_frictwork .and.
associated(meke))
then ;
if (
associated(meke%mom_src))
then 925 do j=js,je ;
do i=is,ie
926 meke%mom_src(i,j) = 0.
929 if (meke%backscatter_Ro_c /= 0.)
then 930 do j=js,je ;
do i=is,ie
931 fath = 0.25*( (abs(g%CoriolisBu(i-1,j-1)) + abs(g%CoriolisBu(i,j))) &
932 +(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j-1))) )
933 shear_mag = sqrt(sh_xx(i,j)*sh_xx(i,j) + &
934 0.25*((sh_xy(i-1,j-1)*sh_xy(i-1,j-1) + sh_xy(i,j)*sh_xy(i,j)) + &
935 (sh_xy(i-1,j)*sh_xy(i-1,j) + sh_xy(i,j-1)*sh_xy(i,j-1))))
936 fath = fath ** meke%backscatter_Ro_pow
937 shear_mag = ( ( shear_mag ** meke%backscatter_Ro_pow ) + 1.e-30 ) &
938 * meke%backscatter_Ro_c
941 roscl = shear_mag / ( fath + shear_mag )
942 meke%mom_src(i,j) = meke%mom_src(i,j) + gv%H_to_kg_m2 * ( &
943 ((str_xx(i,j)-roscl*bhstr_xx(i,j))*(u(i,j,k)-u(i-1,j,k))*g%IdxT(i,j) &
944 -(str_xx(i,j)-roscl*bhstr_xx(i,j))*(v(i,j,k)-v(i,j-1,k))*g%IdyT(i,j)) &
945 +0.25*(((str_xy(i,j)-roscl*bhstr_xy(i,j))*( &
946 (u(i,j+1,k)-u(i,j,k))*g%IdyBu(i,j) &
947 +(v(i+1,j,k)-v(i,j,k))*g%IdxBu(i,j) ) &
948 +(str_xy(i-1,j-1)-roscl*bhstr_xy(i-1,j-1))*( &
949 (u(i-1,j,k)-u(i-1,j-1,k))*g%IdyBu(i-1,j-1) &
950 +(v(i,j-1,k)-v(i-1,j-1,k))*g%IdxBu(i-1,j-1) )) &
951 +((str_xy(i-1,j)-roscl*bhstr_xy(i-1,j))*( &
952 (u(i-1,j+1,k)-u(i-1,j,k))*g%IdyBu(i-1,j) &
953 +(v(i,j,k)-v(i-1,j,k))*g%IdxBu(i-1,j) ) &
954 +(str_xy(i,j-1)-roscl*bhstr_xy(i,j-1))*( &
955 (u(i,j,k)-u(i,j-1,k))*g%IdyBu(i,j-1) &
956 +(v(i+1,j-1,k)-v(i,j-1,k))*g%IdxBu(i,j-1) )) ) )
959 do j=js,je ;
do i=is,ie
960 meke%mom_src(i,j) = meke%mom_src(i,j) + frictwork(i,j,k)
968 if (cs%id_diffu>0)
call post_data(cs%id_diffu, diffu, cs%diag)
969 if (cs%id_diffv>0)
call post_data(cs%id_diffv, diffv, cs%diag)
970 if (cs%id_FrictWork>0)
call post_data(cs%id_FrictWork, frictwork, cs%diag)
971 if (cs%id_Ah_h>0)
call post_data(cs%id_Ah_h, ah_h, cs%diag)
972 if (cs%id_Ah_q>0)
call post_data(cs%id_Ah_q, ah_q, cs%diag)
973 if (cs%id_Kh_h>0)
call post_data(cs%id_Kh_h, kh_h, cs%diag)
974 if (cs%id_Kh_q>0)
call post_data(cs%id_Kh_q, kh_q, cs%diag)
976 if (cs%id_FrictWorkIntz > 0)
then 978 do i=is,ie ; frictworkintz(i,j) = frictwork(i,j,1) ;
enddo 979 do k=2,nz ;
do i=is,ie
980 frictworkintz(i,j) = frictworkintz(i,j) + frictwork(i,j,k)
983 call post_data(cs%id_FrictWorkIntz, frictworkintz, cs%diag)
995 type(time_type),
intent(in) :: Time
999 type(
diag_ctrl),
target,
intent(inout) :: diag
1015 real,
dimension(SZIB_(G),SZJ_(G)) :: u0u, u0v
1016 real,
dimension(SZI_(G),SZJB_(G)) :: v0u, v0v
1027 real :: BoundCorConst
1032 real :: Kh_vel_scale
1033 real :: Ah_vel_scale
1034 real :: Smag_Lap_const
1035 real :: Smag_bi_const
1036 real :: Leith_Lap_const
1037 real :: Leith_bi_const
1042 real :: bound_Cor_vel
1045 logical :: bound_Cor_def
1049 character(len=64) :: inputdir, filename
1050 integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
1051 integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
1055 #include "version_variable.h" 1056 character(len=40) :: mdl =
"MOM_hor_visc" 1058 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1059 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
1060 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
1061 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1063 if (
associated(cs))
then 1064 call mom_error(warning,
"hor_visc_init called with an associated "// &
1065 "control structure.")
1077 cs%bound_Kh = .false. ; cs%better_bound_Kh = .false. ; cs%Smagorinsky_Kh = .false. ; cs%Leith_Kh = .false.
1078 cs%bound_Ah = .false. ; cs%better_bound_Ah = .false. ; cs%Smagorinsky_Ah = .false. ; cs%Leith_Ah = .false.
1079 cs%bound_Coriolis = .false.
1080 cs%Modified_Leith = .false.
1086 call get_param(param_file, mdl,
"GET_ALL_PARAMS", get_all, default=.false.)
1088 call get_param(param_file, mdl,
"LAPLACIAN", cs%Laplacian, &
1089 "If true, use a Laplacian horizontal viscosity.", &
1091 if (cs%Laplacian .or. get_all)
then 1092 call get_param(param_file, mdl,
"KH", kh, &
1093 "The background Laplacian horizontal viscosity.", &
1094 units =
"m2 s-1", default=0.0)
1095 call get_param(param_file, mdl,
"KH_BG_MIN", cs%Kh_bg_min, &
1096 "The minimum value allowed for Laplacian horizontal viscosity, KH.", &
1097 units =
"m2 s-1", default=0.0)
1098 call get_param(param_file, mdl,
"KH_VEL_SCALE", kh_vel_scale, &
1099 "The velocity scale which is multiplied by the grid \n"//&
1100 "spacing to calculate the Laplacian viscosity. \n"//&
1101 "The final viscosity is the largest of this scaled \n"//&
1102 "viscosity, the Smagorinsky and Leith viscosities, and KH.", &
1103 units=
"m s-1", default=0.0)
1105 call get_param(param_file, mdl,
"SMAGORINSKY_KH", cs%Smagorinsky_Kh, &
1106 "If true, use a Smagorinsky nonlinear eddy viscosity.", &
1108 if (cs%Smagorinsky_Kh .or. get_all) &
1109 call get_param(param_file, mdl,
"SMAG_LAP_CONST", smag_lap_const, &
1110 "The nondimensional Laplacian Smagorinsky constant, \n"//&
1111 "often 0.15.", units=
"nondim", default=0.0, &
1112 fail_if_missing = cs%Smagorinsky_Kh)
1114 call get_param(param_file, mdl,
"LEITH_KH", cs%Leith_Kh, &
1115 "If true, use a Leith nonlinear eddy viscosity.", &
1118 call get_param(param_file, mdl,
"MODIFIED_LEITH", cs%Modified_Leith, &
1119 "If true, add a term to Leith viscosity which is \n"//&
1120 "proportional to the gradient of divergence.", &
1123 if (cs%Leith_Kh .or. get_all) &
1124 call get_param(param_file, mdl,
"LEITH_LAP_CONST", leith_lap_const, &
1125 "The nondimensional Laplacian Leith constant, \n"//&
1126 "often ??", units=
"nondim", default=0.0, &
1127 fail_if_missing = cs%Leith_Kh)
1129 call get_param(param_file, mdl,
"BOUND_KH", cs%bound_Kh, &
1130 "If true, the Laplacian coefficient is locally limited \n"//&
1131 "to be stable.", default=.true.)
1132 call get_param(param_file, mdl,
"BETTER_BOUND_KH", cs%better_bound_Kh, &
1133 "If true, the Laplacian coefficient is locally limited \n"//&
1134 "to be stable with a better bounding than just BOUND_KH.", &
1135 default=cs%bound_Kh)
1138 call get_param(param_file, mdl,
"BIHARMONIC", cs%biharmonic, &
1139 "If true, use a biharmonic horizontal viscosity. \n"//&
1140 "BIHARMONIC may be used with LAPLACIAN.", &
1142 if (cs%biharmonic .or. get_all)
then 1143 call get_param(param_file, mdl,
"AH", ah, &
1144 "The background biharmonic horizontal viscosity.", &
1145 units =
"m4 s-1", default=0.0)
1146 call get_param(param_file, mdl,
"AH_VEL_SCALE", ah_vel_scale, &
1147 "The velocity scale which is multiplied by the cube of \n"//&
1148 "the grid spacing to calculate the biharmonic viscosity. \n"//&
1149 "The final viscosity is the largest of this scaled \n"//&
1150 "viscosity, the Smagorinsky and Leith viscosities, and AH.", &
1151 units=
"m s-1", default=0.0)
1152 call get_param(param_file, mdl,
"SMAGORINSKY_AH", cs%Smagorinsky_Ah, &
1153 "If true, use a biharmonic Smagorinsky nonlinear eddy \n"//&
1154 "viscosity.", default=.false.)
1155 call get_param(param_file, mdl,
"LEITH_AH", cs%Leith_Ah, &
1156 "If true, use a biharmonic Leith nonlinear eddy \n"//&
1157 "viscosity.", default=.false.)
1159 call get_param(param_file, mdl,
"BOUND_AH", cs%bound_Ah, &
1160 "If true, the biharmonic coefficient is locally limited \n"//&
1161 "to be stable.", default=.true.)
1162 call get_param(param_file, mdl,
"BETTER_BOUND_AH", cs%better_bound_Ah, &
1163 "If true, the biharmonic coefficient is locally limited \n"//&
1164 "to be stable with a better bounding than just BOUND_AH.", &
1165 default=cs%bound_Ah)
1167 if (cs%Smagorinsky_Ah .or. get_all)
then 1168 call get_param(param_file, mdl,
"SMAG_BI_CONST",smag_bi_const, &
1169 "The nondimensional biharmonic Smagorinsky constant, \n"//&
1170 "typically 0.015 - 0.06.", units=
"nondim", default=0.0, &
1171 fail_if_missing = cs%Smagorinsky_Ah)
1173 call get_param(param_file, mdl,
"BOUND_CORIOLIS", bound_cor_def, default=.false.)
1174 call get_param(param_file, mdl,
"BOUND_CORIOLIS_BIHARM", cs%bound_Coriolis, &
1175 "If true use a viscosity that increases with the square \n"//&
1176 "of the velocity shears, so that the resulting viscous \n"//&
1177 "drag is of comparable magnitude to the Coriolis terms \n"//&
1178 "when the velocity differences between adjacent grid \n"//&
1179 "points is 0.5*BOUND_CORIOLIS_VEL. The default is the \n"//&
1180 "value of BOUND_CORIOLIS (or false).", default=bound_cor_def)
1181 if (cs%bound_Coriolis .or. get_all)
then 1182 call get_param(param_file, mdl,
"MAXVEL", maxvel, default=3.0e8)
1183 bound_cor_vel = maxvel
1184 call get_param(param_file, mdl,
"BOUND_CORIOLIS_VEL", bound_cor_vel, &
1185 "The velocity scale at which BOUND_CORIOLIS_BIHARM causes \n"//&
1186 "the biharmonic drag to have comparable magnitude to the \n"//&
1187 "Coriolis acceleration. The default is set by MAXVEL.", &
1188 units=
"m s-1", default=maxvel)
1192 if (cs%Leith_Ah .or. get_all)
then 1193 call get_param(param_file, mdl,
"LEITH_BI_CONST",leith_bi_const, &
1194 "The nondimensional biharmonic Leith constant, \n"//&
1195 "typical values are thus far undetermined", units=
"nondim", default=0.0, &
1196 fail_if_missing = cs%Leith_Ah)
1201 if (cs%better_bound_Ah .or. cs%better_bound_Kh .or. get_all) &
1202 call get_param(param_file, mdl,
"HORVISC_BOUND_COEF", cs%bound_coef, &
1203 "The nondimensional coefficient of the ratio of the \n"//&
1204 "viscosity bounds to the theoretical maximum for \n"//&
1205 "stability without considering other terms.", units=
"nondim", &
1208 call get_param(param_file, mdl,
"NOSLIP", cs%no_slip, &
1209 "If true, no slip boundary conditions are used; otherwise \n"//&
1210 "free slip boundary conditions are assumed. The \n"//&
1211 "implementation of the free slip BCs on a C-grid is much \n"//&
1212 "cleaner than the no slip BCs. The use of free slip BCs \n"//&
1213 "is strongly encouraged, and no slip BCs are not used with \n"//&
1214 "the biharmonic viscosity.", default=.false.)
1216 call get_param(param_file, mdl,
"USE_KH_BG_2D", cs%use_Kh_bg_2d, &
1217 "If true, read a file containing 2-d background harmonic \n"//&
1218 "viscosities. The final viscosity is the maximum of the other "//&
1219 "terms and this background value.", default=.false.)
1222 if (cs%bound_Kh .or. cs%bound_Ah .or. cs%better_bound_Kh .or. cs%better_bound_Ah) &
1223 call get_param(param_file, mdl,
"DT", dt, &
1224 "The (baroclinic) dynamics time step.", units =
"s", &
1225 fail_if_missing=.true.)
1227 if (cs%no_slip .and. cs%biharmonic) &
1228 call mom_error(fatal,
"ERROR: NOSLIP and BIHARMONIC cannot be defined "// &
1229 "at the same time in MOM.")
1231 if (.not.(cs%Laplacian .or. cs%biharmonic))
then 1233 if ( max(g%domain%niglobal, g%domain%njglobal)>2 )
call mom_error(warning, &
1234 "hor_visc_init: It is usually a very bad idea not to use either "//&
1235 "LAPLACIAN or BIHARMONIC viscosity.")
1239 alloc_(cs%dx2h(isd:ied,jsd:jed)) ; cs%dx2h(:,:) = 0.0
1240 alloc_(cs%dy2h(isd:ied,jsd:jed)) ; cs%dy2h(:,:) = 0.0
1241 alloc_(cs%dx2q(isdb:iedb,jsdb:jedb)) ; cs%dx2q(:,:) = 0.0
1242 alloc_(cs%dy2q(isdb:iedb,jsdb:jedb)) ; cs%dy2q(:,:) = 0.0
1243 alloc_(cs%dx_dyT(isd:ied,jsd:jed)) ; cs%dx_dyT(:,:) = 0.0
1244 alloc_(cs%dy_dxT(isd:ied,jsd:jed)) ; cs%dy_dxT(:,:) = 0.0
1245 alloc_(cs%dx_dyBu(isdb:iedb,jsdb:jedb)) ; cs%dx_dyBu(:,:) = 0.0
1246 alloc_(cs%dy_dxBu(isdb:iedb,jsdb:jedb)) ; cs%dy_dxBu(:,:) = 0.0
1248 if (cs%Laplacian)
then 1249 alloc_(cs%Kh_bg_xx(isd:ied,jsd:jed)) ; cs%Kh_bg_xx(:,:) = 0.0
1250 alloc_(cs%Kh_bg_xy(isdb:iedb,jsdb:jedb)) ; cs%Kh_bg_xy(:,:) = 0.0
1251 if (cs%bound_Kh .or. cs%better_bound_Kh)
then 1252 alloc_(cs%Kh_Max_xx(isdb:iedb,jsdb:jedb)) ; cs%Kh_Max_xx(:,:) = 0.0
1253 alloc_(cs%Kh_Max_xy(isdb:iedb,jsdb:jedb)) ; cs%Kh_Max_xy(:,:) = 0.0
1255 if (cs%Smagorinsky_Kh)
then 1256 alloc_(cs%Laplac_Const_xx(isd:ied,jsd:jed)) ; cs%Laplac_Const_xx(:,:) = 0.0
1257 alloc_(cs%Laplac_Const_xy(isdb:iedb,jsdb:jedb)) ; cs%Laplac_Const_xy(:,:) = 0.0
1259 if (cs%Leith_Kh)
then 1260 alloc_(cs%Laplac3_Const_xx(isd:ied,jsd:jed)) ; cs%Laplac3_Const_xx(:,:) = 0.0
1261 alloc_(cs%Laplac3_Const_xy(isdb:iedb,jsdb:jedb)) ; cs%Laplac3_Const_xy(:,:) = 0.0
1265 alloc_(cs%reduction_xx(isd:ied,jsd:jed)) ; cs%reduction_xx(:,:) = 0.0
1266 alloc_(cs%reduction_xy(isdb:iedb,jsdb:jedb)) ; cs%reduction_xy(:,:) = 0.0
1268 if (cs%use_Kh_bg_2d)
then 1269 alloc_(cs%Kh_bg_2d(isd:ied,jsd:jed)) ; cs%Kh_bg_2d(:,:) = 0.0
1270 call get_param(param_file, mdl,
"KH_BG_2D_FILENAME", filename, &
1271 'The filename containing a 2d map of "Kh".', &
1272 default=
'KH_background_2d.nc')
1273 call get_param(param_file, mdl,
"INPUTDIR", inputdir, default=
".")
1274 inputdir = slasher(inputdir)
1275 call read_data(trim(inputdir)//trim(filename),
'Kh', cs%Kh_bg_2d, &
1276 domain=g%domain%mpp_domain, timelevel=1)
1277 call pass_var(cs%Kh_bg_2d, g%domain)
1280 if (cs%biharmonic)
then 1281 alloc_(cs%Idx2dyCu(isdb:iedb,jsd:jed)) ; cs%Idx2dyCu(:,:) = 0.0
1282 alloc_(cs%Idx2dyCv(isd:ied,jsdb:jedb)) ; cs%Idx2dyCv(:,:) = 0.0
1283 alloc_(cs%Idxdy2u(isdb:iedb,jsd:jed)) ; cs%Idxdy2u(:,:) = 0.0
1284 alloc_(cs%Idxdy2v(isd:ied,jsdb:jedb)) ; cs%Idxdy2v(:,:) = 0.0
1286 alloc_(cs%Ah_bg_xx(isd:ied,jsd:jed)) ; cs%Ah_bg_xx(:,:) = 0.0
1287 alloc_(cs%Ah_bg_xy(isdb:iedb,jsdb:jedb)) ; cs%Ah_bg_xy(:,:) = 0.0
1288 if (cs%bound_Ah .or. cs%better_bound_Ah)
then 1289 alloc_(cs%Ah_Max_xx(isd:ied,jsd:jed)) ; cs%Ah_Max_xx(:,:) = 0.0
1290 alloc_(cs%Ah_Max_xy(isdb:iedb,jsdb:jedb)) ; cs%Ah_Max_xy(:,:) = 0.0
1292 if (cs%Smagorinsky_Ah)
then 1293 alloc_(cs%Biharm_Const_xx(isd:ied,jsd:jed)) ; cs%Biharm_Const_xx(:,:) = 0.0
1294 alloc_(cs%Biharm_Const_xy(isdb:iedb,jsdb:jedb)) ; cs%Biharm_Const_xy(:,:) = 0.0
1295 if (cs%bound_Coriolis)
then 1296 alloc_(cs%Biharm_Const2_xx(isd:ied,jsd:jed)) ; cs%Biharm_Const2_xx(:,:) = 0.0
1297 alloc_(cs%Biharm_Const2_xy(isdb:iedb,jsdb:jedb)) ; cs%Biharm_Const2_xy(:,:) = 0.0
1300 if (cs%Leith_Ah)
then 1301 alloc_(cs%Biharm5_Const_xx(isd:ied,jsd:jed)) ; cs%Biharm5_Const_xx(:,:) = 0.0
1302 alloc_(cs%Biharm5_Const_xy(isdb:iedb,jsdb:jedb)) ; cs%Biharm5_Const_xy(:,:) = 0.0
1306 do j=js-2,jeq+1 ;
do i=is-2,ieq+1
1307 cs%DX2q(i,j) = g%dxBu(i,j)*g%dxBu(i,j) ; cs%DY2q(i,j) = g%dyBu(i,j)*g%dyBu(i,j)
1308 cs%DX_dyBu(i,j) = g%dxBu(i,j)*g%IdyBu(i,j) ; cs%DY_dxBu(i,j) = g%dyBu(i,j)*g%IdxBu(i,j)
1310 do j=jsq-1,jeq+2 ;
do i=isq-1,ieq+2
1311 cs%DX2h(i,j) = g%dxT(i,j)*g%dxT(i,j) ; cs%DY2h(i,j) = g%dyT(i,j)*g%dyT(i,j)
1312 cs%DX_dyT(i,j) = g%dxT(i,j)*g%IdyT(i,j) ; cs%DY_dxT(i,j) = g%dyT(i,j)*g%IdxT(i,j)
1315 do j=jsq,jeq+1 ;
do i=isq,ieq+1
1316 cs%reduction_xx(i,j) = 1.0
1317 if ((g%dy_Cu(i,j) > 0.0) .and. (g%dy_Cu(i,j) < g%dyCu(i,j)) .and. &
1318 (g%dy_Cu(i,j) < g%dyCu(i,j) * cs%reduction_xx(i,j))) &
1319 cs%reduction_xx(i,j) = g%dy_Cu(i,j) / g%dyCu(i,j)
1320 if ((g%dy_Cu(i-1,j) > 0.0) .and. (g%dy_Cu(i-1,j) < g%dyCu(i-1,j)) .and. &
1321 (g%dy_Cu(i-1,j) < g%dyCu(i-1,j) * cs%reduction_xx(i,j))) &
1322 cs%reduction_xx(i,j) = g%dy_Cu(i-1,j) / g%dyCu(i-1,j)
1323 if ((g%dx_Cv(i,j) > 0.0) .and. (g%dx_Cv(i,j) < g%dxCv(i,j)) .and. &
1324 (g%dx_Cv(i,j) < g%dxCv(i,j) * cs%reduction_xx(i,j))) &
1325 cs%reduction_xx(i,j) = g%dx_Cv(i,j) / g%dxCv(i,j)
1326 if ((g%dx_Cv(i,j-1) > 0.0) .and. (g%dx_Cv(i,j-1) < g%dxCv(i,j-1)) .and. &
1327 (g%dx_Cv(i,j-1) < g%dxCv(i,j-1) * cs%reduction_xx(i,j))) &
1328 cs%reduction_xx(i,j) = g%dx_Cv(i,j-1) / g%dxCv(i,j-1)
1331 do j=js-1,jeq ;
do i=is-1,ieq
1332 cs%reduction_xy(i,j) = 1.0
1333 if ((g%dy_Cu(i,j) > 0.0) .and. (g%dy_Cu(i,j) < g%dyCu(i,j)) .and. &
1334 (g%dy_Cu(i,j) < g%dyCu(i,j) * cs%reduction_xy(i,j))) &
1335 cs%reduction_xy(i,j) = g%dy_Cu(i,j) / g%dyCu(i,j)
1336 if ((g%dy_Cu(i,j+1) > 0.0) .and. (g%dy_Cu(i,j+1) < g%dyCu(i,j+1)) .and. &
1337 (g%dy_Cu(i,j+1) < g%dyCu(i,j+1) * cs%reduction_xy(i,j))) &
1338 cs%reduction_xy(i,j) = g%dy_Cu(i,j+1) / g%dyCu(i,j+1)
1339 if ((g%dx_Cv(i,j) > 0.0) .and. (g%dx_Cv(i,j) < g%dxCv(i,j)) .and. &
1340 (g%dx_Cv(i,j) < g%dxCv(i,j) * cs%reduction_xy(i,j))) &
1341 cs%reduction_xy(i,j) = g%dx_Cv(i,j) / g%dxCv(i,j)
1342 if ((g%dx_Cv(i+1,j) > 0.0) .and. (g%dx_Cv(i+1,j) < g%dxCv(i+1,j)) .and. &
1343 (g%dx_Cv(i+1,j) < g%dxCv(i+1,j) * cs%reduction_xy(i,j))) &
1344 cs%reduction_xy(i,j) = g%dx_Cv(i+1,j) / g%dxCv(i+1,j)
1347 if (cs%Laplacian)
then 1350 if (cs%bound_Kh .or. cs%bound_Ah) kh_limit = 0.3 / (dt*4.0)
1351 do j=jsq,jeq+1 ;
do i=isq,ieq+1
1352 grid_sp_h2 = (2.0*cs%DX2h(i,j)*cs%DY2h(i,j)) / (cs%DX2h(i,j) + cs%DY2h(i,j))
1353 grid_sp_h3 = grid_sp_h2*sqrt(grid_sp_h2)
1354 if (cs%Smagorinsky_Kh) cs%LAPLAC_CONST_xx(i,j) = smag_lap_const * grid_sp_h2
1355 if (cs%Leith_Kh) cs%LAPLAC3_CONST_xx(i,j) = leith_lap_const * grid_sp_h3
1357 cs%Kh_bg_xx(i,j) = max(kh, kh_vel_scale * sqrt(grid_sp_h2))
1359 if (cs%use_Kh_bg_2d) cs%Kh_bg_xx(i,j) = max(cs%Kh_bg_2d(i,j), cs%Kh_bg_xx(i,j))
1361 if (cs%bound_Kh .and. .not.cs%better_bound_Kh)
then 1362 cs%Kh_Max_xx(i,j) = kh_limit * grid_sp_h2
1363 cs%Kh_bg_xx(i,j) = min(cs%Kh_bg_xx(i,j), cs%Kh_Max_xx(i,j))
1366 do j=js-1,jeq ;
do i=is-1,ieq
1367 grid_sp_q2 = (2.0*cs%DX2q(i,j)*cs%DY2q(i,j)) / (cs%DX2q(i,j) + cs%DY2q(i,j))
1368 grid_sp_q3 = grid_sp_q2*sqrt(grid_sp_q2)
1369 if (cs%Smagorinsky_Kh) cs%LAPLAC_CONST_xy(i,j) = smag_lap_const * grid_sp_q2
1370 if (cs%Leith_Kh) cs%LAPLAC3_CONST_xy(i,j) = leith_lap_const * grid_sp_q3
1372 cs%Kh_bg_xy(i,j) = max(kh, kh_vel_scale * sqrt(grid_sp_q2))
1374 if (cs%use_Kh_bg_2d) cs%Kh_bg_xy(i,j) = max(cs%Kh_bg_2d(i,j), cs%Kh_bg_xy(i,j))
1376 if (cs%bound_Kh .and. .not.cs%better_bound_Kh)
then 1377 cs%Kh_Max_xy(i,j) = kh_limit * grid_sp_q2
1378 cs%Kh_bg_xy(i,j) = min(cs%Kh_bg_xy(i,j), cs%Kh_Max_xy(i,j))
1383 if (cs%biharmonic)
then 1385 do j=js-1,jeq+1 ;
do i=isq-1,ieq+1
1386 cs%IDX2dyCu(i,j) = (g%IdxCu(i,j)*g%IdxCu(i,j)) * g%IdyCu(i,j)
1387 cs%IDXDY2u(i,j) = g%IdxCu(i,j) * (g%IdyCu(i,j)*g%IdyCu(i,j))
1389 do j=jsq-1,jeq+1 ;
do i=is-1,ieq+1
1390 cs%IDX2dyCv(i,j) = (g%IdxCv(i,j)*g%IdxCv(i,j)) * g%IdyCv(i,j)
1391 cs%IDXDY2v(i,j) = g%IdxCv(i,j) * (g%IdyCv(i,j)*g%IdyCv(i,j))
1394 cs%Ah_bg_xy(:,:) = 0.0
1397 ah_limit = 0.3 / (dt*64.0)
1398 if (cs%Smagorinsky_Ah .and. cs%bound_Coriolis) &
1399 boundcorconst = 1.0 / (5.0*(bound_cor_vel*bound_cor_vel))
1400 do j=jsq,jeq+1 ;
do i=isq,ieq+1
1401 grid_sp_h2 = (2.0*cs%DX2h(i,j)*cs%DY2h(i,j)) / (cs%DX2h(i,j)+cs%DY2h(i,j))
1402 grid_sp_h3 = grid_sp_h2*sqrt(grid_sp_h2)
1404 if (cs%Smagorinsky_Ah)
then 1405 cs%BIHARM_CONST_xx(i,j) = smag_bi_const * (grid_sp_h2 * grid_sp_h2)
1406 if (cs%bound_Coriolis)
then 1407 fmax = max(abs(g%CoriolisBu(i-1,j-1)), abs(g%CoriolisBu(i,j-1)), &
1408 abs(g%CoriolisBu(i-1,j)), abs(g%CoriolisBu(i,j)))
1409 cs%Biharm_Const2_xx(i,j) = (grid_sp_h2 * grid_sp_h2 * grid_sp_h2) * &
1410 (fmax * boundcorconst)
1413 if (cs%Leith_Ah)
then 1414 cs%BIHARM5_CONST_xx(i,j) = leith_bi_const * (grid_sp_h2 * grid_sp_h3)
1417 cs%Ah_bg_xx(i,j) = max(ah, ah_vel_scale * grid_sp_h2 * sqrt(grid_sp_h2))
1418 if (cs%bound_Ah .and. .not.cs%better_bound_Ah)
then 1419 cs%Ah_Max_xx(i,j) = ah_limit * (grid_sp_h2 * grid_sp_h2)
1420 cs%Ah_bg_xx(i,j) = min(cs%Ah_bg_xx(i,j), cs%Ah_Max_xx(i,j))
1423 do j=js-1,jeq ;
do i=is-1,ieq
1424 grid_sp_q2 = (2.0*cs%DX2q(i,j)*cs%DY2q(i,j)) / (cs%DX2q(i,j)+cs%DY2q(i,j))
1425 grid_sp_q3 = grid_sp_q2*sqrt(grid_sp_q2)
1427 if (cs%Smagorinsky_Ah)
then 1428 cs%BIHARM_CONST_xy(i,j) = smag_bi_const * (grid_sp_q2 * grid_sp_q2)
1429 if (cs%bound_Coriolis)
then 1430 cs%Biharm_Const2_xy(i,j) = (grid_sp_q2 * grid_sp_q2 * grid_sp_q2) * &
1431 (abs(g%CoriolisBu(i,j)) * boundcorconst)
1435 if (cs%Leith_Ah)
then 1436 cs%BIHARM5_CONST_xy(i,j) = leith_bi_const * (grid_sp_q2 * grid_sp_q3)
1439 cs%Ah_bg_xy(i,j) = max(ah, ah_vel_scale * grid_sp_q2 * sqrt(grid_sp_q2))
1440 if (cs%bound_Ah .and. .not.cs%better_bound_Ah)
then 1441 cs%Ah_Max_xy(i,j) = ah_limit * (grid_sp_q2 * grid_sp_q2)
1442 cs%Ah_bg_xy(i,j) = min(cs%Ah_bg_xy(i,j), cs%Ah_Max_xy(i,j))
1448 if (cs%Laplacian .and. cs%better_bound_Kh)
then 1450 do j=jsq,jeq+1 ;
do i=isq,ieq+1
1452 (cs%DY2h(i,j) * cs%DY_dxT(i,j) * (g%IdyCu(i,j) + g%IdyCu(i-1,j)) * &
1453 max(g%IdyCu(i,j)*g%IareaCu(i,j), g%IdyCu(i-1,j)*g%IareaCu(i-1,j)) ), &
1454 (cs%DX2h(i,j) * cs%DX_dyT(i,j) * (g%IdxCv(i,j) + g%IdxCv(i,j-1)) * &
1455 max(g%IdxCv(i,j)*g%IareaCv(i,j), g%IdxCv(i,j-1)*g%IareaCv(i,j-1)) ) )
1456 cs%Kh_Max_xx(i,j) = 0.0
1458 cs%Kh_Max_xx(i,j) = cs%bound_coef * 0.25 * idt / denom
1460 do j=js-1,jeq ;
do i=is-1,ieq
1462 (cs%DX2q(i,j) * cs%DX_dyBu(i,j) * (g%IdxCu(i,j+1) + g%IdxCu(i,j)) * &
1463 max(g%IdxCu(i,j)*g%IareaCu(i,j), g%IdxCu(i,j+1)*g%IareaCu(i,j+1)) ), &
1464 (cs%DY2q(i,j) * cs%DY_dxBu(i,j) * (g%IdyCv(i+1,j) + g%IdyCv(i,j)) * &
1465 max(g%IdyCv(i,j)*g%IareaCv(i,j), g%IdyCv(i+1,j)*g%IareaCv(i+1,j)) ) )
1466 cs%Kh_Max_xy(i,j) = 0.0
1468 cs%Kh_Max_xy(i,j) = cs%bound_coef * 0.25 * idt / denom
1474 if (cs%biharmonic .and. cs%better_bound_Ah)
then 1476 do j=js-1,jeq+1 ;
do i=isq-1,ieq+1
1477 u0u(i,j) = cs%IDXDY2u(i,j)*(cs%DY2h(i+1,j)*cs%DY_dxT(i+1,j)*(g%IdyCu(i+1,j) + g%IdyCu(i,j)) + &
1478 cs%DY2h(i,j) * cs%DY_dxT(i,j) * (g%IdyCu(i,j) + g%IdyCu(i-1,j)) ) + &
1479 cs%IDX2dyCu(i,j)*(cs%DX2q(i,j) * cs%DX_dyBu(i,j) * (g%IdxCu(i,j+1) + g%IdxCu(i,j)) + &
1480 cs%DX2q(i,j-1)*cs%DX_dyBu(i,j-1)*(g%IdxCu(i,j) + g%IdxCu(i,j-1)) )
1482 u0v(i,j) = cs%IDXDY2u(i,j)*(cs%DY2h(i+1,j)*cs%DX_dyT(i+1,j)*(g%IdxCv(i+1,j) + g%IdxCv(i+1,j-1)) + &
1483 cs%DY2h(i,j) * cs%DX_dyT(i,j) * (g%IdxCv(i,j) + g%IdxCv(i,j-1)) ) + &
1484 cs%IDX2dyCu(i,j)*(cs%DX2q(i,j) * cs%DY_dxBu(i,j) * (g%IdyCv(i+1,j) + g%IdyCv(i,j)) + &
1485 cs%DX2q(i,j-1)*cs%DY_dxBu(i,j-1)*(g%IdyCv(i+1,j-1) + g%IdyCv(i,j-1)) )
1487 do j=jsq-1,jeq+1 ;
do i=is-1,ieq+1
1488 v0u(i,j) = cs%IDXDY2v(i,j)*(cs%DY2q(i,j) * cs%DX_dyBu(i,j) * (g%IdxCu(i,j+1) + g%IdxCu(i,j)) + &
1489 cs%DY2q(i-1,j)*cs%DX_dyBu(i-1,j)*(g%IdxCu(i-1,j+1) + g%IdxCu(i-1,j)) ) + &
1490 cs%IDX2dyCv(i,j)*(cs%DX2h(i,j+1)*cs%DY_dxT(i,j+1)*(g%IdyCu(i,j+1) + g%IdyCu(i-1,j+1)) + &
1491 cs%DX2h(i,j) * cs%DY_dxT(i,j) * (g%IdyCu(i,j) + g%IdyCu(i-1,j)) )
1493 v0v(i,j) = cs%IDXDY2v(i,j)*(cs%DY2q(i,j) * cs%DY_dxBu(i,j) * (g%IdyCv(i+1,j) + g%IdyCv(i,j)) + &
1494 cs%DY2q(i-1,j)*cs%DY_dxBu(i-1,j)*(g%IdyCv(i,j) + g%IdyCv(i-1,j)) ) + &
1495 cs%IDX2dyCv(i,j)*(cs%DX2h(i,j+1)*cs%DX_dyT(i,j+1)*(g%IdxCv(i,j+1) + g%IdxCv(i,j)) + &
1496 cs%DX2h(i,j) * cs%DX_dyT(i,j) * (g%IdxCv(i,j) + g%IdxCv(i,j-1)) )
1499 do j=jsq,jeq+1 ;
do i=isq,ieq+1
1502 (cs%DY_dxT(i,j)*(g%IdyCu(i,j)*u0u(i,j) + g%IdyCu(i-1,j)*u0u(i-1,j)) + &
1503 cs%DX_dyT(i,j)*(g%IdxCv(i,j)*v0u(i,j) + g%IdxCv(i,j-1)*v0u(i,j-1))) * &
1504 max(g%IdyCu(i,j)*g%IareaCu(i,j), g%IdyCu(i-1,j)*g%IareaCu(i-1,j)) ), &
1506 (cs%DY_dxT(i,j)*(g%IdyCu(i,j)*u0v(i,j) + g%IdyCu(i-1,j)*u0v(i-1,j)) + &
1507 cs%DX_dyT(i,j)*(g%IdxCv(i,j)*v0v(i,j) + g%IdxCv(i,j-1)*v0v(i,j-1))) * &
1508 max(g%IdxCv(i,j)*g%IareaCv(i,j), g%IdxCv(i,j-1)*g%IareaCv(i,j-1)) ) )
1509 cs%Ah_Max_xx(i,j) = 0.0
1511 cs%Ah_Max_xx(i,j) = cs%bound_coef * 0.5 * idt / denom
1514 do j=js-1,jeq ;
do i=is-1,ieq
1517 (cs%DX_dyBu(i,j)*(u0u(i,j+1)*g%IdxCu(i,j+1) + u0u(i,j)*g%IdxCu(i,j)) + &
1518 cs%DY_dxBu(i,j)*(v0u(i+1,j)*g%IdyCv(i+1,j) + v0u(i,j)*g%IdyCv(i,j))) * &
1519 max(g%IdxCu(i,j)*g%IareaCu(i,j), g%IdxCu(i,j+1)*g%IareaCu(i,j+1)) ), &
1521 (cs%DX_dyBu(i,j)*(u0v(i,j+1)*g%IdxCu(i,j+1) + u0v(i,j)*g%IdxCu(i,j)) + &
1522 cs%DY_dxBu(i,j)*(v0v(i+1,j)*g%IdyCv(i+1,j) + v0v(i,j)*g%IdyCv(i,j))) * &
1523 max(g%IdyCv(i,j)*g%IareaCv(i,j), g%IdyCv(i+1,j)*g%IareaCv(i+1,j)) ) )
1524 cs%Ah_Max_xy(i,j) = 0.0
1526 cs%Ah_Max_xy(i,j) = cs%bound_coef * 0.5 * idt / denom
1532 cs%id_diffu = register_diag_field(
'ocean_model',
'diffu', diag%axesCuL, time, &
1533 'Zonal Acceleration from Horizontal Viscosity',
'meter second-2')
1535 cs%id_diffv = register_diag_field(
'ocean_model',
'diffv', diag%axesCvL, time, &
1536 'Meridional Acceleration from Horizontal Viscosity',
'meter second-2')
1538 if (cs%biharmonic)
then 1539 cs%id_Ah_h = register_diag_field(
'ocean_model',
'Ahh', diag%axesTL, time, &
1540 'Biharmonic Horizontal Viscosity at h Points',
'meter4 second-1', &
1541 cmor_field_name=
'difmxybo', cmor_units=
'm4 s-1', &
1542 cmor_long_name=
'Ocean lateral biharmonic viscosity', &
1543 cmor_standard_name=
'ocean_momentum_xy_biharmonic_diffusivity')
1545 cs%id_Ah_q = register_diag_field(
'ocean_model',
'Ahq', diag%axesBL, time, &
1546 'Biharmonic Horizontal Viscosity at q Points',
'meter4 second-1')
1549 if (cs%Laplacian)
then 1550 cs%id_Kh_h = register_diag_field(
'ocean_model',
'Khh', diag%axesTL, time, &
1551 'Laplacian Horizontal Viscosity at h Points',
'meter2 second-1', &
1552 cmor_field_name=
'difmxylo', cmor_units=
'm2 s-1', &
1553 cmor_long_name=
'Ocean lateral Laplacian viscosity', &
1554 cmor_standard_name=
'ocean_momentum_xy_laplacian_diffusivity')
1556 cs%id_Kh_q = register_diag_field(
'ocean_model',
'Khq', diag%axesBL, time, &
1557 'Laplacian Horizontal Viscosity at q Points',
'meter2 second-1')
1560 cs%id_FrictWork = register_diag_field(
'ocean_model',
'FrictWork',diag%axesTL,time,&
1561 'Integral work done by lateral friction terms',
'Watt meter-2')
1563 cs%id_FrictWorkIntz = register_diag_field(
'ocean_model',
'FrictWorkIntz',diag%axesT1,time, &
1564 'Depth integrated work done by lateral friction',
'Watt meter-2', &
1565 cmor_field_name=
'dispkexyfo', cmor_units=
'W m-2', &
1566 cmor_long_name=
'Depth integrated ocean kinetic energy dissipation due to lateral friction',&
1567 cmor_standard_name=
'ocean_kinetic_energy_dissipation_per_unit_area_due_to_xy_friction')
1569 if (cs%Laplacian .or. get_all)
then 1580 if (cs%Laplacian .or. cs%biharmonic)
then 1581 dealloc_(cs%dx2h) ; dealloc_(cs%dx2q) ; dealloc_(cs%dy2h) ; dealloc_(cs%dy2q)
1582 dealloc_(cs%dx_dyT) ; dealloc_(cs%dy_dxT) ; dealloc_(cs%dx_dyBu) ; dealloc_(cs%dy_dxBu)
1583 dealloc_(cs%reduction_xx) ; dealloc_(cs%reduction_xy)
1586 if (cs%Laplacian)
then 1587 dealloc_(cs%Kh_bg_xx) ; dealloc_(cs%Kh_bg_xy)
1588 if (cs%bound_Kh)
then 1589 dealloc_(cs%Kh_Max_xx) ; dealloc_(cs%Kh_Max_xy)
1591 if (cs%Smagorinsky_Kh)
then 1592 dealloc_(cs%Laplac_Const_xx) ; dealloc_(cs%Laplac_Const_xy)
1594 if (cs%Leith_Kh)
then 1595 dealloc_(cs%Laplac3_Const_xx) ; dealloc_(cs%Laplac3_Const_xy)
1599 if (cs%biharmonic)
then 1600 dealloc_(cs%Idx2dyCu) ; dealloc_(cs%Idx2dyCv)
1601 dealloc_(cs%Idxdy2u) ; dealloc_(cs%Idxdy2v)
1602 dealloc_(cs%Ah_bg_xx) ; dealloc_(cs%Ah_bg_xy)
1603 if (cs%bound_Ah)
then 1604 dealloc_(cs%Ah_Max_xx) ; dealloc_(cs%Ah_Max_xy)
1606 if (cs%Smagorinsky_Ah)
then 1607 dealloc_(cs%Biharm_Const_xx) ; dealloc_(cs%Biharm_Const_xy)
1608 if (cs%bound_Coriolis)
then 1609 dealloc_(cs%Biharm_Const2_xx) ; dealloc_(cs%Biharm_Const2_xy)
1612 if (cs%Leith_Ah)
then 1613 dealloc_(cs%Biharm5_Const_xx) ; dealloc_(cs%Biharm5_Const_xy)
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.
integer, parameter, public obc_direction_n
Indicates the boundary is an effective northern boundary.
subroutine, public hor_visc_init(Time, G, param_file, diag, CS)
This subroutine allocates space for and calculates static variables used by this module. The metrics may be 0, 1, or 2-D arrays, while fields like the background viscosities are 2-D arrays. ALLOC is a macro defined in MOM_memory.h to either allocate for dynamic memory, or do nothing when using static memory.
Ocean grid type. See mom_grid for details.
Provides the ocean grid type.
This module contains I/O framework code.
Variable mixing coefficients.
Variable mixing coefficients.
subroutine, public horizontal_viscosity(u, v, h, diffu, diffv, MEKE, VarMix, G, GV, CS, OBC)
This subroutine determines the acceleration due to the horizontal viscosity. A combination of biharmo...
integer, parameter, public obc_direction_e
Indicates the boundary is an effective eastern boundary.
subroutine, public hor_visc_end(CS)
integer, parameter, public obc_none
Controls where open boundary conditions are applied.
subroutine, public mom_error(level, message, all_print)