16 use mom_pointaccel,
only : write_u_accel, write_v_accel, pointaccel_init
25 implicit none ;
private
27 #include <MOM_memory.h>
29 public vertvisc, vertvisc_remnant, vertvisc_coef
30 public vertvisc_limit_vel, vertvisc_init, vertvisc_end
31 public updatecfltruncationvalue
52 logical :: cfl_based_trunc
64 logical :: cflrampingisactivated = .false.
65 type(time_type) :: rampstarttime
67 real allocable_,
dimension(NIMEMB_PTR_,NJMEM_,NK_INTERFACE_) :: &
69 real allocable_,
dimension(NIMEMB_PTR_,NJMEM_,NKMEM_) :: &
71 real allocable_,
dimension(NIMEM_,NJMEMB_PTR_,NK_INTERFACE_) :: &
73 real allocable_,
dimension(NIMEM_,NJMEMB_PTR_,NKMEM_) :: &
75 real,
pointer,
dimension(:,:) :: a1_shelf_u => null()
77 real,
pointer,
dimension(:,:) :: a1_shelf_v => null()
81 logical :: bottomdraglaw
86 logical :: channel_drag
89 logical :: harmonic_visc
97 logical :: direct_stress
99 logical :: dynamic_viscous_ml
105 integer,
pointer :: ntrunc
107 character(len=200) :: u_trunc_file
109 character(len=200) :: v_trunc_file
111 logical :: stokesmixing
119 integer :: id_du_dt_visc = -1, id_dv_dt_visc = -1, id_au_vv = -1, id_av_vv = -1
120 integer :: id_h_u = -1, id_h_v = -1, id_hml_u = -1 , id_hml_v = -1
121 integer :: id_ray_u = -1, id_ray_v = -1, id_taux_bot = -1, id_tauy_bot = -1
122 integer :: id_kv_slow = -1, id_kv_u = -1, id_kv_v = -1
145 subroutine vertvisc(u, v, h, forces, visc, dt, OBC, ADp, CDp, G, GV, US, CS, &
146 taux_bot, tauy_bot, Waves)
150 real,
dimension(SZIB_(G),SZJ_(G),SZK_(GV)), &
152 real,
dimension(SZI_(G),SZJB_(G),SZK_(GV)), &
154 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
158 real,
intent(in) :: dt
164 real,
dimension(SZIB_(G),SZJ_(G)), &
165 optional,
intent(out) :: taux_bot
166 real,
dimension(SZI_(G),SZJB_(G)), &
167 optional,
intent(out) :: tauy_bot
169 optional,
pointer :: waves
178 real :: c1(szib_(g),szk_(g))
180 real :: ray(szib_(g),szk_(g))
196 real :: zds, hfr, h_a
197 real :: surface_stress(szib_(g))
200 logical :: do_i(szib_(g))
201 logical :: dostokesmixing
203 integer :: i, j, k, is, ie, isq, ieq, jsq, jeq, nz, n
204 is = g%isc ; ie = g%iec
205 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB ; nz = g%ke
207 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_vert_friction(visc): "// &
208 "Module must be initialized before it is used.")
210 if (cs%direct_stress)
then
211 hmix = cs%Hmix_stress
214 dt_rho0 = dt/gv%H_to_kg_m2
215 dt_z_to_h = us%s_to_T*dt*gv%Z_to_H
217 h_neglect = gv%H_subroundoff
221 dostokesmixing=.false.
222 if (cs%StokesMixing)
then
223 if (
present(waves)) dostokesmixing =
associated(waves)
224 if (.not. dostokesmixing) &
225 call mom_error(fatal,
"Stokes Mixing called without allocated"//&
226 "Waves Control Structure")
229 do k=1,nz ;
do i=isq,ieq ; ray(i,k) = 0.0 ;
enddo ;
enddo
238 do i=isq,ieq ; do_i(i) = (g%mask2dCu(i,j) > 0) ;
enddo
241 if (dostokesmixing)
then ;
do k=1,nz ;
do i=isq,ieq
242 if (do_i(i)) u(i,j,k) = u(i,j,k) + waves%Us_x(i,j,k)
243 enddo ;
enddo ;
endif
245 if (
associated(adp%du_dt_visc))
then ;
do k=1,nz ;
do i=isq,ieq
246 adp%du_dt_visc(i,j,k) = u(i,j,k)
247 enddo ;
enddo ;
endif
252 if (cs%direct_stress)
then
253 do i=isq,ieq ;
if (do_i(i))
then
254 surface_stress(i) = 0.0
256 stress = dt_rho0 * forces%taux(i,j)
258 h_a = 0.5 * (h(i,j,k) + h(i+1,j,k)) + h_neglect
259 hfr = 1.0 ;
if ((zds+h_a) > hmix) hfr = (hmix - zds) / h_a
260 u(i,j,k) = u(i,j,k) + i_hmix * hfr * stress
261 zds = zds + h_a ;
if (zds >= hmix)
exit
265 surface_stress(i) = dt_rho0 * (g%mask2dCu(i,j)*forces%taux(i,j))
268 if (cs%Channel_drag)
then ;
do k=1,nz ;
do i=isq,ieq
269 ray(i,k) = visc%Ray_u(i,j,k)
270 enddo ;
enddo ;
endif
295 do i=isq,ieq ;
if (do_i(i))
then
296 b_denom_1 = cs%h_u(i,j,1) + dt_z_to_h * (ray(i,1) + cs%a_u(i,j,1))
297 b1(i) = 1.0 / (b_denom_1 + dt_z_to_h*cs%a_u(i,j,2))
298 d1(i) = b_denom_1 * b1(i)
299 u(i,j,1) = b1(i) * (cs%h_u(i,j,1) * u(i,j,1) + surface_stress(i))
301 do k=2,nz ;
do i=isq,ieq ;
if (do_i(i))
then
302 c1(i,k) = dt_z_to_h * cs%a_u(i,j,k) * b1(i)
303 b_denom_1 = cs%h_u(i,j,k) + dt_z_to_h * (ray(i,k) + cs%a_u(i,j,k)*d1(i))
304 b1(i) = 1.0 / (b_denom_1 + dt_z_to_h * cs%a_u(i,j,k+1))
305 d1(i) = b_denom_1 * b1(i)
306 u(i,j,k) = (cs%h_u(i,j,k) * u(i,j,k) + &
307 dt_z_to_h * cs%a_u(i,j,k) * u(i,j,k-1)) * b1(i)
308 endif ;
enddo ;
enddo
312 do k=nz-1,1,-1 ;
do i=isq,ieq ;
if (do_i(i))
then
313 u(i,j,k) = u(i,j,k) + c1(i,k+1) * u(i,j,k+1)
314 endif ;
enddo ;
enddo
316 if (
associated(adp%du_dt_visc))
then ;
do k=1,nz ;
do i=isq,ieq
317 adp%du_dt_visc(i,j,k) = (u(i,j,k) - adp%du_dt_visc(i,j,k))*idt
318 enddo ;
enddo ;
endif
320 if (
associated(visc%taux_shelf))
then ;
do i=isq,ieq
321 visc%taux_shelf(i,j) = -rho0*us%s_to_T*cs%a1_shelf_u(i,j)*u(i,j,1)
324 if (
PRESENT(taux_bot))
then
326 taux_bot(i,j) = rho0 * (u(i,j,nz)*us%s_to_T*cs%a_u(i,j,nz+1))
328 if (cs%Channel_drag)
then ;
do k=1,nz ;
do i=isq,ieq
329 taux_bot(i,j) = taux_bot(i,j) + rho0 * (us%s_to_T*ray(i,k)*u(i,j,k))
330 enddo ;
enddo ;
endif
334 if (dostokesmixing)
then ;
do k=1,nz ;
do i=isq,ieq
335 if (do_i(i)) u(i,j,k) = u(i,j,k) - waves%Us_x(i,j,k)
336 enddo ;
enddo ;
endif
346 do i=is,ie ; do_i(i) = (g%mask2dCv(i,j) > 0) ;
enddo
349 if (dostokesmixing)
then ;
do k=1,nz ;
do i=is,ie
350 if (do_i(i)) v(i,j,k) = v(i,j,k) + waves%Us_y(i,j,k)
351 enddo ;
enddo ;
endif
353 if (
associated(adp%dv_dt_visc))
then ;
do k=1,nz ;
do i=is,ie
354 adp%dv_dt_visc(i,j,k) = v(i,j,k)
355 enddo ;
enddo ;
endif
360 if (cs%direct_stress)
then
361 do i=is,ie ;
if (do_i(i))
then
362 surface_stress(i) = 0.0
364 stress = dt_rho0 * forces%tauy(i,j)
366 h_a = 0.5 * (h(i,j,k) + h(i,j+1,k))
367 hfr = 1.0 ;
if ((zds+h_a) > hmix) hfr = (hmix - zds) / h_a
368 v(i,j,k) = v(i,j,k) + i_hmix * hfr * stress
369 zds = zds + h_a ;
if (zds >= hmix)
exit
373 surface_stress(i) = dt_rho0 * (g%mask2dCv(i,j)*forces%tauy(i,j))
376 if (cs%Channel_drag)
then ;
do k=1,nz ;
do i=is,ie
377 ray(i,k) = visc%Ray_v(i,j,k)
378 enddo ;
enddo ;
endif
380 do i=is,ie ;
if (do_i(i))
then
381 b_denom_1 = cs%h_v(i,j,1) + dt_z_to_h * (ray(i,1) + cs%a_v(i,j,1))
382 b1(i) = 1.0 / (b_denom_1 + dt_z_to_h*cs%a_v(i,j,2))
383 d1(i) = b_denom_1 * b1(i)
384 v(i,j,1) = b1(i) * (cs%h_v(i,j,1) * v(i,j,1) + surface_stress(i))
386 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
387 c1(i,k) = dt_z_to_h * cs%a_v(i,j,k) * b1(i)
388 b_denom_1 = cs%h_v(i,j,k) + dt_z_to_h * (ray(i,k) + cs%a_v(i,j,k)*d1(i))
389 b1(i) = 1.0 / (b_denom_1 + dt_z_to_h * cs%a_v(i,j,k+1))
390 d1(i) = b_denom_1 * b1(i)
391 v(i,j,k) = (cs%h_v(i,j,k) * v(i,j,k) + dt_z_to_h * cs%a_v(i,j,k) * v(i,j,k-1)) * b1(i)
392 endif ;
enddo ;
enddo
393 do k=nz-1,1,-1 ;
do i=is,ie ;
if (do_i(i))
then
394 v(i,j,k) = v(i,j,k) + c1(i,k+1) * v(i,j,k+1)
395 endif ;
enddo ;
enddo
397 if (
associated(adp%dv_dt_visc))
then ;
do k=1,nz ;
do i=is,ie
398 adp%dv_dt_visc(i,j,k) = (v(i,j,k) - adp%dv_dt_visc(i,j,k))*idt
399 enddo ;
enddo ;
endif
401 if (
associated(visc%tauy_shelf))
then ;
do i=is,ie
402 visc%tauy_shelf(i,j) = -rho0*us%s_to_T*cs%a1_shelf_v(i,j)*v(i,j,1)
405 if (
present(tauy_bot))
then
407 tauy_bot(i,j) = rho0 * (v(i,j,nz)*us%s_to_T*cs%a_v(i,j,nz+1))
409 if (cs%Channel_drag)
then ;
do k=1,nz ;
do i=is,ie
410 tauy_bot(i,j) = tauy_bot(i,j) + rho0 * (us%s_to_T*ray(i,k)*v(i,j,k))
411 enddo ;
enddo ;
endif
415 if (dostokesmixing)
then ;
do k=1,nz ;
do i=is,ie
416 if (do_i(i)) v(i,j,k) = v(i,j,k) - waves%Us_y(i,j,k)
417 enddo ;
enddo ;
endif
421 call vertvisc_limit_vel(u, v, h, adp, cdp, forces, visc, dt, g, gv, us, cs)
424 if (
associated(obc))
then
425 do n=1,obc%number_of_segments
426 if (obc%segment(n)%specified)
then
427 if (obc%segment(n)%is_N_or_S)
then
428 j = obc%segment(n)%HI%JsdB
429 do k=1,nz ;
do i=obc%segment(n)%HI%isd,obc%segment(n)%HI%ied
430 v(i,j,k) = obc%segment(n)%normal_vel(i,j,k)
432 elseif (obc%segment(n)%is_E_or_W)
then
433 i = obc%segment(n)%HI%IsdB
434 do k=1,nz ;
do j=obc%segment(n)%HI%jsd,obc%segment(n)%HI%jed
435 u(i,j,k) = obc%segment(n)%normal_vel(i,j,k)
443 if (cs%id_du_dt_visc > 0) &
444 call post_data(cs%id_du_dt_visc, adp%du_dt_visc, cs%diag)
445 if (cs%id_dv_dt_visc > 0) &
446 call post_data(cs%id_dv_dt_visc, adp%dv_dt_visc, cs%diag)
447 if (
present(taux_bot) .and. (cs%id_taux_bot > 0)) &
448 call post_data(cs%id_taux_bot, taux_bot, cs%diag)
449 if (
present(tauy_bot) .and. (cs%id_tauy_bot > 0)) &
450 call post_data(cs%id_tauy_bot, tauy_bot, cs%diag)
452 end subroutine vertvisc
458 subroutine vertvisc_remnant(visc, visc_rem_u, visc_rem_v, dt, G, GV, US, CS)
462 real,
dimension(SZIB_(G),SZJ_(G),SZK_(GV)), &
463 intent(inout) :: visc_rem_u
466 real,
dimension(SZI_(G),SZJB_(G),SZK_(GV)), &
467 intent(inout) :: visc_rem_v
470 real,
intent(in) :: dt
477 real :: c1(szib_(g),szk_(g))
479 real :: ray(szib_(g),szk_(g))
483 logical :: do_i(szib_(g))
485 integer :: i, j, k, is, ie, isq, ieq, jsq, jeq, nz
486 is = g%isc ; ie = g%iec
487 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB ; nz = g%ke
489 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_vert_friction(visc): "// &
490 "Module must be initialized before it is used.")
492 dt_z_to_h = us%s_to_T*dt*gv%Z_to_H
494 do k=1,nz ;
do i=isq,ieq ; ray(i,k) = 0.0 ;
enddo ;
enddo
501 do i=isq,ieq ; do_i(i) = (g%mask2dCu(i,j) > 0) ;
enddo
503 if (cs%Channel_drag)
then ;
do k=1,nz ;
do i=isq,ieq
504 ray(i,k) = visc%Ray_u(i,j,k)
505 enddo ;
enddo ;
endif
507 do i=isq,ieq ;
if (do_i(i))
then
508 b_denom_1 = cs%h_u(i,j,1) + dt_z_to_h * (ray(i,1) + cs%a_u(i,j,1))
509 b1(i) = 1.0 / (b_denom_1 + dt_z_to_h*cs%a_u(i,j,2))
510 d1(i) = b_denom_1 * b1(i)
511 visc_rem_u(i,j,1) = b1(i) * cs%h_u(i,j,1)
513 do k=2,nz ;
do i=isq,ieq ;
if (do_i(i))
then
514 c1(i,k) = dt_z_to_h * cs%a_u(i,j,k)*b1(i)
515 b_denom_1 = cs%h_u(i,j,k) + dt_z_to_h * (ray(i,k) + cs%a_u(i,j,k)*d1(i))
516 b1(i) = 1.0 / (b_denom_1 + dt_z_to_h * cs%a_u(i,j,k+1))
517 d1(i) = b_denom_1 * b1(i)
518 visc_rem_u(i,j,k) = (cs%h_u(i,j,k) + dt_z_to_h * cs%a_u(i,j,k) * visc_rem_u(i,j,k-1)) * b1(i)
519 endif ;
enddo ;
enddo
520 do k=nz-1,1,-1 ;
do i=isq,ieq ;
if (do_i(i))
then
521 visc_rem_u(i,j,k) = visc_rem_u(i,j,k) + c1(i,k+1)*visc_rem_u(i,j,k+1)
523 endif ;
enddo ;
enddo
532 do i=is,ie ; do_i(i) = (g%mask2dCv(i,j) > 0) ;
enddo
534 if (cs%Channel_drag)
then ;
do k=1,nz ;
do i=is,ie
535 ray(i,k) = visc%Ray_v(i,j,k)
536 enddo ;
enddo ;
endif
538 do i=is,ie ;
if (do_i(i))
then
539 b_denom_1 = cs%h_v(i,j,1) + dt_z_to_h * (ray(i,1) + cs%a_v(i,j,1))
540 b1(i) = 1.0 / (b_denom_1 + dt_z_to_h*cs%a_v(i,j,2))
541 d1(i) = b_denom_1 * b1(i)
542 visc_rem_v(i,j,1) = b1(i) * cs%h_v(i,j,1)
544 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
545 c1(i,k) = dt_z_to_h * cs%a_v(i,j,k)*b1(i)
546 b_denom_1 = cs%h_v(i,j,k) + dt_z_to_h * (ray(i,k) + cs%a_v(i,j,k)*d1(i))
547 b1(i) = 1.0 / (b_denom_1 + dt_z_to_h * cs%a_v(i,j,k+1))
548 d1(i) = b_denom_1 * b1(i)
549 visc_rem_v(i,j,k) = (cs%h_v(i,j,k) + dt_z_to_h * cs%a_v(i,j,k) * visc_rem_v(i,j,k-1)) * b1(i)
550 endif ;
enddo ;
enddo
551 do k=nz-1,1,-1 ;
do i=is,ie ;
if (do_i(i))
then
552 visc_rem_v(i,j,k) = visc_rem_v(i,j,k) + c1(i,k+1)*visc_rem_v(i,j,k+1)
553 endif ;
enddo ;
enddo
557 call uvchksum(
"visc_rem_[uv]", visc_rem_u, visc_rem_v, g%HI,haloshift=0)
560 end subroutine vertvisc_remnant
566 subroutine vertvisc_coef(u, v, h, forces, visc, dt, G, GV, US, CS, OBC)
570 real,
dimension(SZIB_(G),SZJ_(G),SZK_(GV)), &
572 real,
dimension(SZI_(G),SZJB_(G),SZK_(GV)), &
574 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
578 real,
intent(in) :: dt
588 real,
dimension(SZIB_(G),SZK_(G)) :: &
595 real,
dimension(SZIB_(G),SZK_(G)+1) :: &
602 real,
dimension(SZIB_(G)) :: &
615 real,
allocatable,
dimension(:,:) :: hml_u
616 real,
allocatable,
dimension(:,:) :: hml_v
617 real,
allocatable,
dimension(:,:,:) :: kv_u
618 real,
allocatable,
dimension(:,:,:) :: kv_v
619 real :: zcol(szi_(g))
633 logical,
dimension(SZIB_(G)) :: do_i, do_i_shelf
634 logical :: do_any_shelf
635 integer,
dimension(SZIB_(G)) :: &
638 integer :: i, j, k, is, ie, js, je, isq, ieq, jsq, jeq, nz
639 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
640 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB ; nz = g%ke
642 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_vert_friction(coef): "// &
643 "Module must be initialized before it is used.")
645 h_neglect = gv%H_subroundoff
646 i_hbbl(:) = 1.0 / (cs%Hbbl + h_neglect)
647 i_valbl = 0.0 ;
if (cs%harm_BL_val > 0.0) i_valbl = 1.0 / cs%harm_BL_val
649 if (cs%id_Kv_u > 0)
then
650 allocate(kv_u(g%IsdB:g%IedB,g%jsd:g%jed,g%ke)) ; kv_u(:,:,:) = 0.0
653 if (cs%id_Kv_v > 0)
then
654 allocate(kv_v(g%isd:g%ied,g%JsdB:g%JedB,g%ke)) ; kv_v(:,:,:) = 0.0
657 if (cs%debug .or. (cs%id_hML_u > 0))
then
658 allocate(hml_u(g%IsdB:g%IedB,g%jsd:g%jed)) ; hml_u(:,:) = 0.0
660 if (cs%debug .or. (cs%id_hML_v > 0))
then
661 allocate(hml_v(g%isd:g%ied,g%JsdB:g%JedB)) ; hml_v(:,:) = 0.0
664 if ((
associated(visc%taux_shelf) .or.
associated(forces%frac_shelf_u)) .and. &
665 .not.
associated(cs%a1_shelf_u))
then
666 allocate(cs%a1_shelf_u(g%IsdB:g%IedB,g%jsd:g%jed)) ; cs%a1_shelf_u(:,:)=0.0
668 if ((
associated(visc%tauy_shelf) .or.
associated(forces%frac_shelf_v)) .and. &
669 .not.
associated(cs%a1_shelf_v))
then
670 allocate(cs%a1_shelf_v(g%isd:g%ied,g%JsdB:g%JedB)) ; cs%a1_shelf_v(:,:)=0.0
677 do i=isq,ieq ; do_i(i) = (g%mask2dCu(i,j) > 0) ;
enddo
679 if (cs%bottomdraglaw)
then ;
do i=isq,ieq
680 kv_bbl(i) = visc%Kv_bbl_u(i,j)
681 bbl_thick(i) = visc%bbl_thick_u(i,j) * gv%Z_to_H
682 if (do_i(i)) i_hbbl(i) = 1.0 / (bbl_thick(i) + h_neglect)
685 do k=1,nz ;
do i=isq,ieq ;
if (do_i(i))
then
686 h_harm(i,k) = 2.0*h(i,j,k)*h(i+1,j,k) / (h(i,j,k)+h(i+1,j,k)+h_neglect)
687 h_arith(i,k) = 0.5*(h(i+1,j,k)+h(i,j,k))
688 h_delta(i,k) = h(i+1,j,k) - h(i,j,k)
689 endif ;
enddo ;
enddo
691 dmin(i) = min(g%bathyT(i,j), g%bathyT(i+1,j)) * gv%Z_to_H
696 if (
associated(obc))
then ;
if (obc%number_of_segments > 0)
then
697 do i=isq,ieq ;
if (do_i(i) .and. (obc%segnum_u(i,j) /= obc_none))
then
698 if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e)
then
699 do k=1,nz ; h_harm(i,k) = h(i,j,k) ; h_arith(i,k) = h(i,j,k) ; h_delta(i,k) = 0. ;
enddo
700 dmin(i) = g%bathyT(i,j) * gv%Z_to_H
702 elseif (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_w)
then
703 do k=1,nz ; h_harm(i,k) = h(i+1,j,k) ; h_arith(i,k) = h(i+1,j,k) ; h_delta(i,k) = 0. ;
enddo
704 dmin(i) = g%bathyT(i+1,j) * gv%Z_to_H
715 if (cs%harmonic_visc)
then
716 do i=isq,ieq ; z_i(i,nz+1) = 0.0 ;
enddo
717 do k=nz,1,-1 ;
do i=isq,ieq ;
if (do_i(i))
then
718 hvel(i,k) = h_harm(i,k)
719 if (u(i,j,k) * h_delta(i,k) < 0)
then
720 z2 = z_i(i,k+1) ; botfn = 1.0 / (1.0 + 0.09*z2*z2*z2*z2*z2*z2)
721 hvel(i,k) = (1.0-botfn)*h_harm(i,k) + botfn*h_arith(i,k)
723 z_i(i,k) = z_i(i,k+1) + h_harm(i,k)*i_hbbl(i)
724 endif ;
enddo ;
enddo
726 do i=isq,ieq ; zh(i) = 0.0 ; z_i(i,nz+1) = 0.0 ;
enddo
727 do i=isq,ieq+1 ; zcol(i) = -g%bathyT(i,j) * gv%Z_to_H ;
enddo
729 do i=isq,ieq+1 ; zcol(i) = zcol(i) + h(i,j,k) ;
enddo
730 do i=isq,ieq ;
if (do_i(i))
then
731 zh(i) = zh(i) + h_harm(i,k)
733 z_clear = max(zcol(i),zcol(i+1)) + dmin(i)
734 if (zi_dir(i) < 0) z_clear = zcol(i) + dmin(i)
735 if (zi_dir(i) > 0) z_clear = zcol(i+1) + dmin(i)
737 z_i(i,k) = max(zh(i), z_clear) * i_hbbl(i)
739 hvel(i,k) = h_arith(i,k)
740 if (u(i,j,k) * h_delta(i,k) > 0)
then
741 if (zh(i) * i_hbbl(i) < cs%harm_BL_val)
then
742 hvel(i,k) = h_harm(i,k)
744 z2_wt = 1.0 ;
if (zh(i) * i_hbbl(i) < 2.0*cs%harm_BL_val) &
745 z2_wt = max(0.0, min(1.0, zh(i) * i_hbbl(i) * i_valbl - 1.0))
746 z2 = z2_wt * (max(zh(i), z_clear) * i_hbbl(i))
747 botfn = 1.0 / (1.0 + 0.09*z2*z2*z2*z2*z2*z2)
748 hvel(i,k) = (1.0-botfn)*h_arith(i,k) + botfn*h_harm(i,k)
756 call find_coupling_coef(a_cpl, hvel, do_i, h_harm, bbl_thick, kv_bbl, z_i, h_ml, &
757 dt, j, g, gv, us, cs, visc, forces, work_on_u=.true., obc=obc)
758 if (
allocated(hml_u))
then
759 do i=isq,ieq ;
if (do_i(i))
then ; hml_u(i,j) = h_ml(i) ;
endif ;
enddo
762 do_any_shelf = .false.
763 if (
associated(forces%frac_shelf_u))
then
765 cs%a1_shelf_u(i,j) = 0.0
766 do_i_shelf(i) = (do_i(i) .and. forces%frac_shelf_u(i,j) > 0.0)
767 if (do_i_shelf(i)) do_any_shelf = .true.
769 if (do_any_shelf)
then
770 if (cs%harmonic_visc)
then
771 call find_coupling_coef(a_shelf, hvel, do_i_shelf, h_harm, bbl_thick, &
772 kv_bbl, z_i, h_ml, dt, j, g, gv, us, cs, &
773 visc, forces, work_on_u=.true., obc=obc, shelf=.true.)
776 do i=isq,ieq ;
if (do_i_shelf(i))
then
777 zh(i) = 0.0 ; ztop_min(i) = min(zcol(i), zcol(i+1))
778 i_htbl(i) = 1.0 / (visc%tbl_thick_shelf_u(i,j)*gv%Z_to_H + h_neglect)
781 do i=isq,ieq+1 ; zcol(i) = zcol(i) - h(i,j,k) ;
enddo
782 do i=isq,ieq ;
if (do_i_shelf(i))
then
783 zh(i) = zh(i) + h_harm(i,k)
785 hvel_shelf(i,k) = hvel(i,k)
786 if (u(i,j,k) * h_delta(i,k) > 0)
then
787 if (zh(i) * i_htbl(i) < cs%harm_BL_val)
then
788 hvel_shelf(i,k) = min(hvel(i,k), h_harm(i,k))
790 z2_wt = 1.0 ;
if (zh(i) * i_htbl(i) < 2.0*cs%harm_BL_val) &
791 z2_wt = max(0.0, min(1.0, zh(i) * i_htbl(i) * i_valbl - 1.0))
792 z2 = z2_wt * (max(zh(i), ztop_min(i) - min(zcol(i),zcol(i+1))) * i_htbl(i))
793 topfn = 1.0 / (1.0 + 0.09*z2**6)
794 hvel_shelf(i,k) = min(hvel(i,k), (1.0-topfn)*h_arith(i,k) + topfn*h_harm(i,k))
799 call find_coupling_coef(a_shelf, hvel_shelf, do_i_shelf, h_harm, &
800 bbl_thick, kv_bbl, z_i, h_ml, dt, j, g, gv, us, cs, &
801 visc, forces, work_on_u=.true., obc=obc, shelf=.true.)
803 do i=isq,ieq ;
if (do_i_shelf(i)) cs%a1_shelf_u(i,j) = a_shelf(i,1) ;
enddo
807 if (do_any_shelf)
then
808 do k=1,nz+1 ;
do i=isq,ieq ;
if (do_i_shelf(i))
then
809 cs%a_u(i,j,k) = forces%frac_shelf_u(i,j) * a_shelf(i,k) + &
810 (1.0-forces%frac_shelf_u(i,j)) * a_cpl(i,k)
814 elseif (do_i(i))
then
815 cs%a_u(i,j,k) = a_cpl(i,k)
816 endif ;
enddo ;
enddo
817 do k=1,nz ;
do i=isq,ieq ;
if (do_i_shelf(i))
then
819 cs%h_u(i,j,k) = forces%frac_shelf_u(i,j) * hvel_shelf(i,k) + &
820 (1.0-forces%frac_shelf_u(i,j)) * hvel(i,k)
821 elseif (do_i(i))
then
822 cs%h_u(i,j,k) = hvel(i,k)
823 endif ;
enddo ;
enddo
825 do k=1,nz+1 ;
do i=isq,ieq ;
if (do_i(i)) cs%a_u(i,j,k) = a_cpl(i,k) ;
enddo ;
enddo
826 do k=1,nz ;
do i=isq,ieq ;
if (do_i(i)) cs%h_u(i,j,k) = hvel(i,k) ;
enddo ;
enddo
830 if (cs%id_Kv_u > 0)
then
831 do k=1,nz ;
do i=isq,ieq
832 if (do_i(i)) kv_u(i,j,k) = 0.5 * gv%H_to_Z*(cs%a_u(i,j,k)+cs%a_u(i,j,k+1)) * cs%h_u(i,j,k)
844 do i=is,ie ; do_i(i) = (g%mask2dCv(i,j) > 0) ;
enddo
846 if (cs%bottomdraglaw)
then ;
do i=is,ie
847 kv_bbl(i) = visc%Kv_bbl_v(i,j)
848 bbl_thick(i) = visc%bbl_thick_v(i,j) * gv%Z_to_H
849 if (do_i(i)) i_hbbl(i) = 1.0 / bbl_thick(i)
852 do k=1,nz ;
do i=is,ie ;
if (do_i(i))
then
853 h_harm(i,k) = 2.0*h(i,j,k)*h(i,j+1,k) / (h(i,j,k)+h(i,j+1,k)+h_neglect)
854 h_arith(i,k) = 0.5*(h(i,j+1,k)+h(i,j,k))
855 h_delta(i,k) = h(i,j+1,k) - h(i,j,k)
856 endif ;
enddo ;
enddo
858 dmin(i) = min(g%bathyT(i,j), g%bathyT(i,j+1)) * gv%Z_to_H
863 if (
associated(obc))
then ;
if (obc%number_of_segments > 0)
then
864 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_v(i,j) /= obc_none))
then
865 if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n)
then
866 do k=1,nz ; h_harm(i,k) = h(i,j,k) ; h_arith(i,k) = h(i,j,k) ; h_delta(i,k) = 0. ;
enddo
867 dmin(i) = g%bathyT(i,j) * gv%Z_to_H
869 elseif (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_s)
then
870 do k=1,nz ; h_harm(i,k) = h(i,j+1,k) ; h_arith(i,k) = h(i,j+1,k) ; h_delta(i,k) = 0. ;
enddo
871 dmin(i) = g%bathyT(i,j+1) * gv%Z_to_H
882 if (cs%harmonic_visc)
then
883 do i=is,ie ; z_i(i,nz+1) = 0.0 ;
enddo
885 do k=nz,1,-1 ;
do i=is,ie ;
if (do_i(i))
then
886 hvel(i,k) = h_harm(i,k)
887 if (v(i,j,k) * h_delta(i,k) < 0)
then
888 z2 = z_i(i,k+1) ; botfn = 1.0 / (1.0 + 0.09*z2*z2*z2*z2*z2*z2)
889 hvel(i,k) = (1.0-botfn)*h_harm(i,k) + botfn*h_arith(i,k)
891 z_i(i,k) = z_i(i,k+1) + h_harm(i,k)*i_hbbl(i)
892 endif ;
enddo ;
enddo
895 zh(i) = 0.0 ; z_i(i,nz+1) = 0.0
896 zcol1(i) = -g%bathyT(i,j) * gv%Z_to_H
897 zcol2(i) = -g%bathyT(i,j+1) * gv%Z_to_H
899 do k=nz,1,-1 ;
do i=is,ie ;
if (do_i(i))
then
900 zh(i) = zh(i) + h_harm(i,k)
901 zcol1(i) = zcol1(i) + h(i,j,k) ; zcol2(i) = zcol2(i) + h(i,j+1,k)
903 z_clear = max(zcol1(i),zcol2(i)) + dmin(i)
904 if (zi_dir(i) < 0) z_clear = zcol1(i) + dmin(i)
905 if (zi_dir(i) > 0) z_clear = zcol2(i) + dmin(i)
907 z_i(i,k) = max(zh(i), z_clear) * i_hbbl(i)
909 hvel(i,k) = h_arith(i,k)
910 if (v(i,j,k) * h_delta(i,k) > 0)
then
911 if (zh(i) * i_hbbl(i) < cs%harm_BL_val)
then
912 hvel(i,k) = h_harm(i,k)
914 z2_wt = 1.0 ;
if (zh(i) * i_hbbl(i) < 2.0*cs%harm_BL_val) &
915 z2_wt = max(0.0, min(1.0, zh(i) * i_hbbl(i) * i_valbl - 1.0))
916 z2 = z2_wt * (max(zh(i), max(zcol1(i),zcol2(i)) + dmin(i)) * i_hbbl(i))
917 botfn = 1.0 / (1.0 + 0.09*z2*z2*z2*z2*z2*z2)
918 hvel(i,k) = (1.0-botfn)*h_arith(i,k) + botfn*h_harm(i,k)
922 endif ;
enddo ;
enddo
925 call find_coupling_coef(a_cpl, hvel, do_i, h_harm, bbl_thick, kv_bbl, z_i, h_ml, &
926 dt, j, g, gv, us, cs, visc, forces, work_on_u=.false., obc=obc)
927 if (
allocated(hml_v))
then
928 do i=is,ie ;
if (do_i(i))
then ; hml_v(i,j) = h_ml(i) ;
endif ;
enddo
930 do_any_shelf = .false.
931 if (
associated(forces%frac_shelf_v))
then
933 cs%a1_shelf_v(i,j) = 0.0
934 do_i_shelf(i) = (do_i(i) .and. forces%frac_shelf_v(i,j) > 0.0)
935 if (do_i_shelf(i)) do_any_shelf = .true.
937 if (do_any_shelf)
then
938 if (cs%harmonic_visc)
then
939 call find_coupling_coef(a_shelf, hvel, do_i_shelf, h_harm, bbl_thick, &
940 kv_bbl, z_i, h_ml, dt, j, g, gv, us, cs, visc, &
941 forces, work_on_u=.false., obc=obc, shelf=.true.)
944 do i=is,ie ;
if (do_i_shelf(i))
then
945 zh(i) = 0.0 ; ztop_min(i) = min(zcol1(i), zcol2(i))
946 i_htbl(i) = 1.0 / (visc%tbl_thick_shelf_v(i,j)*gv%Z_to_H + h_neglect)
949 do i=is,ie ;
if (do_i_shelf(i))
then
950 zcol1(i) = zcol1(i) - h(i,j,k) ; zcol2(i) = zcol2(i) - h(i,j+1,k)
951 zh(i) = zh(i) + h_harm(i,k)
953 hvel_shelf(i,k) = hvel(i,k)
954 if (v(i,j,k) * h_delta(i,k) > 0)
then
955 if (zh(i) * i_htbl(i) < cs%harm_BL_val)
then
956 hvel_shelf(i,k) = min(hvel(i,k), h_harm(i,k))
958 z2_wt = 1.0 ;
if (zh(i) * i_htbl(i) < 2.0*cs%harm_BL_val) &
959 z2_wt = max(0.0, min(1.0, zh(i) * i_htbl(i) * i_valbl - 1.0))
960 z2 = z2_wt * (max(zh(i), ztop_min(i) - min(zcol1(i),zcol2(i))) * i_htbl(i))
961 topfn = 1.0 / (1.0 + 0.09*z2**6)
962 hvel_shelf(i,k) = min(hvel(i,k), (1.0-topfn)*h_arith(i,k) + topfn*h_harm(i,k))
967 call find_coupling_coef(a_shelf, hvel_shelf, do_i_shelf, h_harm, &
968 bbl_thick, kv_bbl, z_i, h_ml, dt, j, g, gv, us, cs, &
969 visc, forces, work_on_u=.false., obc=obc, shelf=.true.)
971 do i=is,ie ;
if (do_i_shelf(i)) cs%a1_shelf_v(i,j) = a_shelf(i,1) ;
enddo
975 if (do_any_shelf)
then
976 do k=1,nz+1 ;
do i=is,ie ;
if (do_i_shelf(i))
then
977 cs%a_v(i,j,k) = forces%frac_shelf_v(i,j) * a_shelf(i,k) + &
978 (1.0-forces%frac_shelf_v(i,j)) * a_cpl(i,k)
982 elseif (do_i(i))
then
983 cs%a_v(i,j,k) = a_cpl(i,k)
984 endif ;
enddo ;
enddo
985 do k=1,nz ;
do i=is,ie ;
if (do_i_shelf(i))
then
987 cs%h_v(i,j,k) = forces%frac_shelf_v(i,j) * hvel_shelf(i,k) + &
988 (1.0-forces%frac_shelf_v(i,j)) * hvel(i,k)
989 elseif (do_i(i))
then
990 cs%h_v(i,j,k) = hvel(i,k)
991 endif ;
enddo ;
enddo
993 do k=1,nz+1 ;
do i=is,ie ;
if (do_i(i)) cs%a_v(i,j,k) = a_cpl(i,k) ;
enddo ;
enddo
994 do k=1,nz ;
do i=is,ie ;
if (do_i(i)) cs%h_v(i,j,k) = hvel(i,k) ;
enddo ;
enddo
998 if (cs%id_Kv_v > 0)
then
999 do k=1,nz ;
do i=is,ie
1000 if (do_i(i)) kv_v(i,j,k) = 0.5 * gv%H_to_Z*(cs%a_v(i,j,k)+cs%a_v(i,j,k+1)) * cs%h_v(i,j,k)
1007 call uvchksum(
"vertvisc_coef h_[uv]", cs%h_u, &
1008 cs%h_v, g%HI,haloshift=0, scale=gv%H_to_m*us%s_to_T)
1009 call uvchksum(
"vertvisc_coef a_[uv]", cs%a_u, &
1010 cs%a_v, g%HI, haloshift=0, scale=us%Z_to_m*us%s_to_T)
1011 if (
allocated(hml_u) .and.
allocated(hml_v)) &
1012 call uvchksum(
"vertvisc_coef hML_[uv]", hml_u, hml_v, &
1013 g%HI, haloshift=0, scale=gv%H_to_m)
1017 if (cs%id_Kv_slow > 0)
call post_data(cs%id_Kv_slow, visc%Kv_slow, cs%diag)
1018 if (cs%id_Kv_u > 0)
call post_data(cs%id_Kv_u, kv_u, cs%diag)
1019 if (cs%id_Kv_v > 0)
call post_data(cs%id_Kv_v, kv_v, cs%diag)
1020 if (cs%id_au_vv > 0)
call post_data(cs%id_au_vv, cs%a_u, cs%diag)
1021 if (cs%id_av_vv > 0)
call post_data(cs%id_av_vv, cs%a_v, cs%diag)
1022 if (cs%id_h_u > 0)
call post_data(cs%id_h_u, cs%h_u, cs%diag)
1023 if (cs%id_h_v > 0)
call post_data(cs%id_h_v, cs%h_v, cs%diag)
1024 if (cs%id_hML_u > 0)
call post_data(cs%id_hML_u, hml_u, cs%diag)
1025 if (cs%id_hML_v > 0)
call post_data(cs%id_hML_v, hml_v, cs%diag)
1027 if (
allocated(hml_u))
deallocate(hml_u)
1028 if (
allocated(hml_v))
deallocate(hml_v)
1030 end subroutine vertvisc_coef
1035 subroutine find_coupling_coef(a_cpl, hvel, do_i, h_harm, bbl_thick, kv_bbl, z_i, h_ml, &
1036 dt, j, G, GV, US, CS, visc, forces, work_on_u, OBC, shelf)
1040 real,
dimension(SZIB_(G),SZK_(GV)+1), &
1041 intent(out) :: a_cpl
1042 real,
dimension(SZIB_(G),SZK_(GV)), &
1044 logical,
dimension(SZIB_(G)), &
1046 real,
dimension(SZIB_(G),SZK_(GV)), &
1047 intent(in) :: h_harm
1049 real,
dimension(SZIB_(G)),
intent(in) :: bbl_thick
1050 real,
dimension(SZIB_(G)),
intent(in) :: kv_bbl
1051 real,
dimension(SZIB_(G),SZK_(GV)+1), &
1054 real,
dimension(SZIB_(G)),
intent(out) :: h_ml
1055 integer,
intent(in) :: j
1056 real,
intent(in) :: dt
1060 logical,
intent(in) :: work_on_u
1063 logical,
optional,
intent(in) :: shelf
1068 real,
dimension(SZIB_(G)) :: &
1077 real,
dimension(SZIB_(G),SZK_(GV)+1) :: &
1093 logical :: do_shelf, do_OBCs
1094 integer :: i, k, is, ie, max_nk
1101 if (work_on_u)
then ; is = g%IscB ; ie = g%IecB
1102 else ; is = g%isc ; ie = g%iec ;
endif
1104 h_neglect = gv%H_subroundoff
1109 i_amax = (1.0e-10*us%Z_to_m) * dt*us%s_to_T
1111 do_shelf = .false. ;
if (
present(shelf)) do_shelf = shelf
1113 if (
associated(obc))
then ; do_obcs = (obc%number_of_segments > 0) ;
endif
1118 do i=is,ie ; kv_tot(i,1) = 0.0 ;
enddo
1119 if ((gv%nkml>0) .or. do_shelf)
then ;
do k=2,nz ;
do i=is,ie
1120 if (do_i(i)) kv_tot(i,k) = cs%Kv
1121 enddo ;
enddo ;
else
1122 i_hmix = 1.0 / (cs%Hmix + h_neglect)
1123 do i=is,ie ; z_t(i) = h_neglect*i_hmix ;
enddo
1124 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1125 z_t(i) = z_t(i) + h_harm(i,k-1)*i_hmix
1126 kv_tot(i,k) = cs%Kv + cs%Kvml / ((z_t(i)*z_t(i)) * &
1127 (1.0 + 0.09*z_t(i)*z_t(i)*z_t(i)*z_t(i)*z_t(i)*z_t(i)))
1128 endif ;
enddo ;
enddo
1131 do i=is,ie ;
if (do_i(i))
then
1132 if (cs%bottomdraglaw)
then
1134 if (r < bbl_thick(i))
then
1135 a_cpl(i,nz+1) = kv_bbl(i) / (i_amax*kv_bbl(i) + r*gv%H_to_Z)
1137 a_cpl(i,nz+1) = kv_bbl(i) / (i_amax*kv_bbl(i) + bbl_thick(i)*gv%H_to_Z)
1140 a_cpl(i,nz+1) = cs%Kvbbl / (0.5*hvel(i,nz)*gv%H_to_Z + i_amax*cs%Kvbbl)
1144 if (
associated(visc%Kv_shear))
then
1147 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1148 kv_add(i,k) = 0.5*(visc%Kv_shear(i,j,k) + visc%Kv_shear(i+1,j,k))
1149 endif ;
enddo ;
enddo
1151 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_u(i,j) /= obc_none))
then
1152 if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e)
then
1153 do k=2,nz ; kv_add(i,k) = visc%Kv_shear(i,j,k) ;
enddo
1154 elseif (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_w)
then
1155 do k=2,nz ; kv_add(i,k) = visc%Kv_shear(i+1,j,k) ;
enddo
1159 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1160 kv_tot(i,k) = kv_tot(i,k) + kv_add(i,k)
1161 endif ;
enddo ;
enddo
1163 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1164 kv_add(i,k) = 0.5*(visc%Kv_shear(i,j,k) + visc%Kv_shear(i,j+1,k))
1165 endif ;
enddo ;
enddo
1167 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_v(i,j) /= obc_none))
then
1168 if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n)
then
1169 do k=2,nz ; kv_add(i,k) = visc%Kv_shear(i,j,k) ;
enddo
1170 elseif (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_s)
then
1171 do k=2,nz ; kv_add(i,k) = visc%Kv_shear(i,j+1,k) ;
enddo
1175 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1176 kv_tot(i,k) = kv_tot(i,k) + kv_add(i,k)
1177 endif ;
enddo ;
enddo
1181 if (
associated(visc%Kv_shear_Bu))
then
1183 do k=2,nz ;
do i=is,ie ;
If (do_i(i))
then
1184 kv_tot(i,k) = kv_tot(i,k) + (0.5)*(visc%Kv_shear_Bu(i,j-1,k) + visc%Kv_shear_Bu(i,j,k))
1185 endif ;
enddo ;
enddo
1187 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1188 kv_tot(i,k) = kv_tot(i,k) + (0.5)*(visc%Kv_shear_Bu(i-1,j,k) + visc%Kv_shear_Bu(i,j,k))
1189 endif ;
enddo ;
enddo
1194 if (
associated(visc%Kv_slow) .and. (visc%add_Kv_slow))
then
1198 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1199 kv_add(i,k) = kv_add(i,k) + 0.5 * (visc%Kv_slow(i,j,k) + visc%Kv_slow(i+1,j,k))
1201 endif ;
enddo ;
enddo
1204 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_u(i,j) /= obc_none))
then
1205 if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e)
then
1206 do k=2,nz ; kv_add(i,k) = kv_add(i,k) + visc%Kv_slow(i,j,k) ;
enddo
1208 elseif (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_w)
then
1209 do k=2,nz ; kv_add(i,k) = kv_add(i,k) + visc%Kv_slow(i+1,j,k) ;
enddo
1214 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1215 kv_tot(i,k) = kv_tot(i,k) + kv_add(i,k)
1216 endif ;
enddo ;
enddo
1219 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1220 kv_add(i,k) = kv_add(i,k) + 0.5*(visc%Kv_slow(i,j,k) + visc%Kv_slow(i,j+1,k))
1221 endif ;
enddo ;
enddo
1224 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_v(i,j) /= obc_none))
then
1225 if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n)
then
1226 do k=2,nz ; kv_add(i,k) = kv_add(i,k) + visc%Kv_slow(i,j,k) ;
enddo
1227 elseif (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_s)
then
1228 do k=2,nz ; kv_add(i,k) = kv_add(i,k) + visc%Kv_slow(i,j+1,k) ;
enddo
1232 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1233 kv_tot(i,k) = kv_tot(i,k) + kv_add(i,k)
1234 endif ;
enddo ;
enddo
1238 do k=nz,2,-1 ;
do i=is,ie ;
if (do_i(i))
then
1242 botfn = 1.0 / (1.0 + 0.09*z2*z2*z2*z2*z2*z2)
1244 if (cs%bottomdraglaw)
then
1245 kv_tot(i,k) = kv_tot(i,k) + (kv_bbl(i) - cs%Kv)*botfn
1246 r = 0.5*(hvel(i,k) + hvel(i,k-1))
1247 if (r > bbl_thick(i))
then
1248 h_shear = ((1.0 - botfn) * r + botfn*bbl_thick(i))
1253 kv_tot(i,k) = kv_tot(i,k) + (cs%Kvbbl-cs%Kv)*botfn
1254 h_shear = 0.5*(hvel(i,k) + hvel(i,k-1) + h_neglect)
1258 a_cpl(i,k) = kv_tot(i,k) / (h_shear*gv%H_to_Z + i_amax*kv_tot(i,k))
1259 endif ;
enddo ;
enddo
1263 do i=is,ie ;
if (do_i(i))
then
1265 kv_tbl(i) = visc%Kv_tbl_shelf_u(i,j)
1266 tbl_thick(i) = visc%tbl_thick_shelf_u(i,j) * gv%Z_to_H
1268 kv_tbl(i) = visc%Kv_tbl_shelf_v(i,j)
1269 tbl_thick(i) = visc%tbl_thick_shelf_v(i,j) * gv%Z_to_H
1274 if (0.5*hvel(i,1) > tbl_thick(i))
then
1275 a_cpl(i,1) = kv_tbl(i) / (tbl_thick(i)*gv%H_to_Z + i_amax*kv_tbl(i))
1277 a_cpl(i,1) = kv_tbl(i) / (0.5*hvel(i,1)*gv%H_to_Z + i_amax*kv_tbl(i))
1281 do k=2,nz ;
do i=is,ie ;
if (do_i(i))
then
1282 z_t(i) = z_t(i) + hvel(i,k-1) / tbl_thick(i)
1283 topfn = 1.0 / (1.0 + 0.09 * z_t(i)**6)
1285 r = 0.5*(hvel(i,k)+hvel(i,k-1))
1286 if (r > tbl_thick(i))
then
1287 h_shear = ((1.0 - topfn) * r + topfn*tbl_thick(i))
1292 a_top = topfn * kv_tbl(i)
1293 a_cpl(i,k) = a_cpl(i,k) + a_top / (h_shear*gv%H_to_Z + i_amax*a_top)
1294 endif ;
enddo ;
enddo
1295 elseif (cs%dynamic_viscous_ML .or. (gv%nkml>0))
then
1297 do i=is,ie ;
if (do_i(i))
then
1298 if (gv%nkml>0) nk_visc(i) = real(gv%nkml+1)
1300 u_star(i) = 0.5*(forces%ustar(i,j) + forces%ustar(i+1,j))
1301 absf(i) = 0.5*(abs(g%CoriolisBu(i,j-1)) + abs(g%CoriolisBu(i,j)))
1302 if (cs%dynamic_viscous_ML) nk_visc(i) = visc%nkml_visc_u(i,j) + 1
1304 u_star(i) = 0.5*(forces%ustar(i,j) + forces%ustar(i,j+1))
1305 absf(i) = 0.5*(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j)))
1306 if (cs%dynamic_viscous_ML) nk_visc(i) = visc%nkml_visc_v(i,j) + 1
1308 h_ml(i) = h_neglect ; z_t(i) = 0.0
1309 max_nk = max(max_nk,ceiling(nk_visc(i) - 1.0))
1312 if (do_obcs)
then ;
if (work_on_u)
then
1313 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_u(i,j) /= obc_none))
then
1314 if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e) &
1315 u_star(i) = forces%ustar(i,j)
1316 if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_w) &
1317 u_star(i) = forces%ustar(i+1,j)
1320 do i=is,ie ;
if (do_i(i) .and. (obc%segnum_v(i,j) /= obc_none))
then
1321 if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n) &
1322 u_star(i) = forces%ustar(i,j)
1323 if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_s) &
1324 u_star(i) = forces%ustar(i,j+1)
1328 do k=1,max_nk ;
do i=is,ie ;
if (do_i(i))
then
1329 if (k+1 <= nk_visc(i))
then
1330 h_ml(i) = h_ml(i) + hvel(i,k)
1331 elseif (k < nk_visc(i))
then
1332 h_ml(i) = h_ml(i) + (nk_visc(i) - k) * hvel(i,k)
1334 endif ;
enddo ;
enddo
1336 do k=2,max_nk ;
do i=is,ie ;
if (do_i(i))
then ;
if (k < nk_visc(i))
then
1338 z_t(i) = z_t(i) + hvel(i,k-1)
1339 temp1 = (z_t(i)*h_ml(i) - z_t(i)*z_t(i))*gv%H_to_Z
1342 visc_ml = u_star(i) * 0.41 * (temp1*u_star(i)) / (absf(i)*temp1 + h_ml(i)*u_star(i))
1343 a_ml = visc_ml / (0.25*(hvel(i,k)+hvel(i,k-1) + h_neglect) * gv%H_to_Z + 0.5*i_amax*visc_ml)
1345 if (a_ml > a_cpl(i,k)) a_cpl(i,k) = a_ml
1346 endif ;
endif ;
enddo ;
enddo
1349 end subroutine find_coupling_coef
1354 subroutine vertvisc_limit_vel(u, v, h, ADp, CDp, forces, visc, dt, G, GV, US, CS)
1358 real,
dimension(SZIB_(G),SZJ_(G),SZK_(GV)), &
1360 real,
dimension(SZI_(G),SZJB_(G),SZK_(GV)), &
1362 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
1368 real,
intent(in) :: dt
1378 real :: vel_report(szib_(g),szjb_(g))
1379 real :: u_old(szib_(g),szj_(g),szk_(g))
1380 real :: v_old(szi_(g),szjb_(g),szk_(g))
1381 logical :: trunc_any, dowrite(szib_(g),szjb_(g))
1382 integer :: i, j, k, is, ie, js, je, isq, ieq, jsq, jeq, nz
1383 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1384 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
1387 truncvel = 0.9*maxvel
1388 h_report = 6.0 * gv%Angstrom_H
1389 dt_rho0 = dt / gv%Rho0
1391 if (len_trim(cs%u_trunc_file) > 0)
then
1395 do i=isq,ieq ; dowrite(i,j) = .false. ;
enddo
1396 if (cs%CFL_based_trunc)
then
1397 do i=isq,ieq ; vel_report(i,j) = 3.0e8 ;
enddo
1398 do k=1,nz ;
do i=isq,ieq
1399 if (abs(u(i,j,k)) < cs%vel_underflow) u(i,j,k) = 0.0
1400 if (u(i,j,k) < 0.0)
then
1401 cfl = (-u(i,j,k) * dt) * (g%dy_Cu(i,j) * g%IareaT(i+1,j))
1403 cfl = (u(i,j,k) * dt) * (g%dy_Cu(i,j) * g%IareaT(i,j))
1405 if (cfl > cs%CFL_trunc) trunc_any = .true.
1406 if (cfl > cs%CFL_report)
then
1407 dowrite(i,j) = .true.
1408 vel_report(i,j) = min(vel_report(i,j), abs(u(i,j,k)))
1412 do i=isq,ieq; vel_report(i,j) = maxvel;
enddo
1413 do k=1,nz ;
do i=isq,ieq
1414 if (abs(u(i,j,k)) < cs%vel_underflow)
then ; u(i,j,k) = 0.0
1415 elseif (abs(u(i,j,k)) > maxvel)
then
1416 dowrite(i,j) = .true. ; trunc_any = .true.
1421 do i=isq,ieq ;
if (dowrite(i,j))
then
1422 u_old(i,j,:) = u(i,j,:)
1425 if (trunc_any)
then ;
if (cs%CFL_based_trunc)
then
1426 do k=1,nz ;
do i=isq,ieq
1427 if ((u(i,j,k) * (dt * g%dy_Cu(i,j))) * g%IareaT(i+1,j) < -cs%CFL_trunc)
then
1428 u(i,j,k) = (-0.9*cs%CFL_trunc) * (g%areaT(i+1,j) / (dt * g%dy_Cu(i,j)))
1429 if (h(i,j,k) + h(i+1,j,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1430 elseif ((u(i,j,k) * (dt * g%dy_Cu(i,j))) * g%IareaT(i,j) > cs%CFL_trunc)
then
1431 u(i,j,k) = (0.9*cs%CFL_trunc) * (g%areaT(i,j) / (dt * g%dy_Cu(i,j)))
1432 if (h(i,j,k) + h(i+1,j,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1436 do k=1,nz ;
do i=isq,ieq ;
if (abs(u(i,j,k)) > maxvel)
then
1437 u(i,j,k) = sign(truncvel,u(i,j,k))
1438 if (h(i,j,k) + h(i+1,j,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1439 endif ;
enddo ;
enddo
1443 if (cs%CFL_based_trunc)
then
1445 do k=1,nz ;
do j=js,je ;
do i=isq,ieq
1446 if (abs(u(i,j,k)) < cs%vel_underflow)
then ; u(i,j,k) = 0.0
1447 elseif ((u(i,j,k) * (dt * g%dy_Cu(i,j))) * g%IareaT(i+1,j) < -cs%CFL_trunc)
then
1448 u(i,j,k) = (-0.9*cs%CFL_trunc) * (g%areaT(i+1,j) / (dt * g%dy_Cu(i,j)))
1449 if (h(i,j,k) + h(i+1,j,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1450 elseif ((u(i,j,k) * (dt * g%dy_Cu(i,j))) * g%IareaT(i,j) > cs%CFL_trunc)
then
1451 u(i,j,k) = (0.9*cs%CFL_trunc) * (g%areaT(i,j) / (dt * g%dy_Cu(i,j)))
1452 if (h(i,j,k) + h(i+1,j,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1454 enddo ;
enddo ;
enddo
1457 do k=1,nz ;
do j=js,je ;
do i=isq,ieq
1458 if (abs(u(i,j,k)) < cs%vel_underflow)
then ; u(i,j,k) = 0.0
1459 elseif (abs(u(i,j,k)) > maxvel)
then
1460 u(i,j,k) = sign(truncvel,u(i,j,k))
1461 if (h(i,j,k) + h(i+1,j,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1463 enddo ;
enddo ;
enddo
1467 if (len_trim(cs%u_trunc_file) > 0)
then
1468 do j=js,je;
do i=isq,ieq ;
if (dowrite(i,j))
then
1471 call write_u_accel(i, j, u_old, h, adp, cdp, dt, g, gv, us, cs%PointAccel_CSp, &
1472 vel_report(i,j), forces%taux(i,j)*dt_rho0, a=cs%a_u, hv=cs%h_u)
1473 endif ;
enddo ;
enddo
1476 if (len_trim(cs%v_trunc_file) > 0)
then
1480 do i=is,ie ; dowrite(i,j) = .false. ;
enddo
1481 if (cs%CFL_based_trunc)
then
1482 do i=is,ie ; vel_report(i,j) = 3.0e8 ;
enddo
1483 do k=1,nz ;
do i=is,ie
1484 if (abs(v(i,j,k)) < cs%vel_underflow) v(i,j,k) = 0.0
1485 if (v(i,j,k) < 0.0)
then
1486 cfl = (-v(i,j,k) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j+1))
1488 cfl = (v(i,j,k) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j))
1490 if (cfl > cs%CFL_trunc) trunc_any = .true.
1491 if (cfl > cs%CFL_report)
then
1492 dowrite(i,j) = .true.
1493 vel_report(i,j) = min(vel_report(i,j), abs(v(i,j,k)))
1497 do i=is,ie ; vel_report(i,j) = maxvel ;
enddo
1498 do k=1,nz ;
do i=is,ie
1499 if (abs(v(i,j,k)) < cs%vel_underflow)
then ; v(i,j,k) = 0.0
1500 elseif (abs(v(i,j,k)) > maxvel)
then
1501 dowrite(i,j) = .true. ; trunc_any = .true.
1506 do i=is,ie ;
if (dowrite(i,j))
then
1507 v_old(i,j,:) = v(i,j,:)
1510 if (trunc_any)
then ;
if (cs%CFL_based_trunc)
then
1511 do k=1,nz;
do i=is,ie
1512 if ((v(i,j,k) * (dt * g%dx_Cv(i,j))) * g%IareaT(i,j+1) < -cs%CFL_trunc)
then
1513 v(i,j,k) = (-0.9*cs%CFL_trunc) * (g%areaT(i,j+1) / (dt * g%dx_Cv(i,j)))
1514 if (h(i,j,k) + h(i,j+1,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1515 elseif ((v(i,j,k) * (dt * g%dx_Cv(i,j))) * g%IareaT(i,j) > cs%CFL_trunc)
then
1516 v(i,j,k) = (0.9*cs%CFL_trunc) * (g%areaT(i,j) / (dt * g%dx_Cv(i,j)))
1517 if (h(i,j,k) + h(i,j+1,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1521 do k=1,nz ;
do i=is,ie ;
if (abs(v(i,j,k)) > maxvel)
then
1522 v(i,j,k) = sign(truncvel,v(i,j,k))
1523 if (h(i,j,k) + h(i,j+1,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1524 endif ;
enddo ;
enddo
1528 if (cs%CFL_based_trunc)
then
1530 do k=1,nz ;
do j=jsq,jeq ;
do i=is,ie
1531 if (abs(v(i,j,k)) < cs%vel_underflow)
then ; v(i,j,k) = 0.0
1532 elseif ((v(i,j,k) * (dt * g%dx_Cv(i,j))) * g%IareaT(i,j+1) < -cs%CFL_trunc)
then
1533 v(i,j,k) = (-0.9*cs%CFL_trunc) * (g%areaT(i,j+1) / (dt * g%dx_Cv(i,j)))
1534 if (h(i,j,k) + h(i,j+1,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1535 elseif ((v(i,j,k) * (dt * g%dx_Cv(i,j))) * g%IareaT(i,j) > cs%CFL_trunc)
then
1536 v(i,j,k) = (0.9*cs%CFL_trunc) * (g%areaT(i,j) / (dt * g%dx_Cv(i,j)))
1537 if (h(i,j,k) + h(i,j+1,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1539 enddo ;
enddo ;
enddo
1542 do k=1,nz ;
do j=jsq,jeq ;
do i=is,ie
1543 if (abs(v(i,j,k)) < cs%vel_underflow)
then ; v(i,j,k) = 0.0
1544 elseif (abs(v(i,j,k)) > maxvel)
then
1545 v(i,j,k) = sign(truncvel,v(i,j,k))
1546 if (h(i,j,k) + h(i,j+1,k) > h_report) cs%ntrunc = cs%ntrunc + 1
1548 enddo ;
enddo ;
enddo
1552 if (len_trim(cs%v_trunc_file) > 0)
then
1553 do j=jsq,jeq;
do i=is,ie ;
if (dowrite(i,j))
then
1556 call write_v_accel(i, j, v_old, h, adp, cdp, dt, g, gv, us, cs%PointAccel_CSp, &
1557 vel_report(i,j), forces%tauy(i,j)*dt_rho0, a=cs%a_v, hv=cs%h_v)
1558 endif ;
enddo ;
enddo
1561 end subroutine vertvisc_limit_vel
1564 subroutine vertvisc_init(MIS, Time, G, GV, US, param_file, diag, ADp, dirs, &
1567 target,
intent(in) :: mis
1570 type(time_type),
target,
intent(in) :: time
1575 type(
diag_ctrl),
target,
intent(inout) :: diag
1578 integer,
target,
intent(inout) :: ntrunc
1583 real :: hmix_str_dflt
1586 integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb, nz
1588 #include "version_variable.h"
1589 character(len=40) :: mdl =
"MOM_vert_friction"
1590 character(len=40) :: thickness_units
1592 if (
associated(cs))
then
1593 call mom_error(warning,
"vertvisc_init called with an associated "// &
1594 "control structure.")
1599 if (gv%Boussinesq) then; thickness_units =
"m"
1600 else; thickness_units =
"kg m-2";
endif
1602 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = g%ke
1603 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1605 cs%diag => diag ; cs%ntrunc => ntrunc ; ntrunc = 0
1609 call get_param(param_file, mdl,
"BOTTOMDRAGLAW", cs%bottomdraglaw, &
1610 "If true, the bottom stress is calculated with a drag "//&
1611 "law of the form c_drag*|u|*u. The velocity magnitude "//&
1612 "may be an assumed value or it may be based on the "//&
1613 "actual velocity in the bottommost HBBL, depending on "//&
1614 "LINEAR_DRAG.", default=.true.)
1615 call get_param(param_file, mdl,
"CHANNEL_DRAG", cs%Channel_drag, &
1616 "If true, the bottom drag is exerted directly on each "//&
1617 "layer proportional to the fraction of the bottom it "//&
1618 "overlies.", default=.false.)
1619 call get_param(param_file, mdl,
"DIRECT_STRESS", cs%direct_stress, &
1620 "If true, the wind stress is distributed over the "//&
1621 "topmost HMIX_STRESS of fluid (like in HYCOM), and KVML "//&
1622 "may be set to a very small value.", default=.false.)
1623 call get_param(param_file, mdl,
"DYNAMIC_VISCOUS_ML", cs%dynamic_viscous_ML, &
1624 "If true, use a bulk Richardson number criterion to "//&
1625 "determine the mixed layer thickness for viscosity.", &
1627 call get_param(param_file, mdl,
"U_TRUNC_FILE", cs%u_trunc_file, &
1628 "The absolute path to a file into which the accelerations "//&
1629 "leading to zonal velocity truncations are written. "//&
1630 "Undefine this for efficiency if this diagnostic is not "//&
1631 "needed.", default=
" ", debuggingparam=.true.)
1632 call get_param(param_file, mdl,
"V_TRUNC_FILE", cs%v_trunc_file, &
1633 "The absolute path to a file into which the accelerations "//&
1634 "leading to meridional velocity truncations are written. "//&
1635 "Undefine this for efficiency if this diagnostic is not "//&
1636 "needed.", default=
" ", debuggingparam=.true.)
1637 call get_param(param_file, mdl,
"HARMONIC_VISC", cs%harmonic_visc, &
1638 "If true, use the harmonic mean thicknesses for "//&
1639 "calculating the vertical viscosity.", default=.false.)
1640 call get_param(param_file, mdl,
"HARMONIC_BL_SCALE", cs%harm_BL_val, &
1641 "A scale to determine when water is in the boundary "//&
1642 "layers based solely on harmonic mean thicknesses for "//&
1643 "the purpose of determining the extent to which the "//&
1644 "thicknesses used in the viscosities are upwinded.", &
1645 default=0.0, units=
"nondim")
1646 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false.)
1649 call get_param(param_file, mdl,
"HMIX_FIXED", cs%Hmix, &
1650 "The prescribed depth over which the near-surface "//&
1651 "viscosity and diffusivity are elevated when the bulk "//&
1652 "mixed layer is not used.", units=
"m", scale=gv%m_to_H, &
1653 unscaled=hmix_m, fail_if_missing=.true.)
1654 if (cs%direct_stress)
then
1655 if (gv%nkml < 1)
then
1656 call get_param(param_file, mdl,
"HMIX_STRESS", cs%Hmix_stress, &
1657 "The depth over which the wind stress is applied if "//&
1658 "DIRECT_STRESS is true.", units=
"m", default=hmix_m, scale=gv%m_to_H)
1660 call get_param(param_file, mdl,
"HMIX_STRESS", cs%Hmix_stress, &
1661 "The depth over which the wind stress is applied if "//&
1662 "DIRECT_STRESS is true.", units=
"m", fail_if_missing=.true., scale=gv%m_to_H)
1664 if (cs%Hmix_stress <= 0.0)
call mom_error(fatal,
"vertvisc_init: " // &
1665 "HMIX_STRESS must be set to a positive value if DIRECT_STRESS is true.")
1667 call get_param(param_file, mdl,
"KV", cs%Kv, &
1668 "The background kinematic viscosity in the interior. "//&
1669 "The molecular value, ~1e-6 m2 s-1, may be used.", &
1670 units=
"m2 s-1", fail_if_missing=.true., scale=us%m2_s_to_Z2_T, unscaled=kv_dflt)
1672 if (gv%nkml < 1)
call get_param(param_file, mdl,
"KVML", cs%Kvml, &
1673 "The kinematic viscosity in the mixed layer. A typical "//&
1674 "value is ~1e-2 m2 s-1. KVML is not used if "//&
1675 "BULKMIXEDLAYER is true. The default is set by KV.", &
1676 units=
"m2 s-1", default=kv_dflt, scale=us%m2_s_to_Z2_T)
1677 if (.not.cs%bottomdraglaw)
call get_param(param_file, mdl,
"KVBBL", cs%Kvbbl, &
1678 "The kinematic viscosity in the benthic boundary layer. "//&
1679 "A typical value is ~1e-2 m2 s-1. KVBBL is not used if "//&
1680 "BOTTOMDRAGLAW is true. The default is set by KV.", &
1681 units=
"m2 s-1", default=kv_dflt, scale=us%m2_s_to_Z2_T)
1682 call get_param(param_file, mdl,
"HBBL", cs%Hbbl, &
1683 "The thickness of a bottom boundary layer with a "//&
1684 "viscosity of KVBBL if BOTTOMDRAGLAW is not defined, or "//&
1685 "the thickness over which near-bottom velocities are "//&
1686 "averaged for the drag law if BOTTOMDRAGLAW is defined "//&
1687 "but LINEAR_DRAG is not.", units=
"m", fail_if_missing=.true., scale=gv%m_to_H)
1688 call get_param(param_file, mdl,
"MAXVEL", cs%maxvel, &
1689 "The maximum velocity allowed before the velocity "//&
1690 "components are truncated.", units=
"m s-1", default=3.0e8)
1691 call get_param(param_file, mdl,
"CFL_BASED_TRUNCATIONS", cs%CFL_based_trunc, &
1692 "If true, base truncations on the CFL number, and not an "//&
1693 "absolute speed.", default=.true.)
1694 call get_param(param_file, mdl,
"CFL_TRUNCATE", cs%CFL_trunc, &
1695 "The value of the CFL number that will cause velocity "//&
1696 "components to be truncated; instability can occur past 0.5.", &
1697 units=
"nondim", default=0.5)
1698 call get_param(param_file, mdl,
"CFL_REPORT", cs%CFL_report, &
1699 "The value of the CFL number that causes accelerations "//&
1700 "to be reported; the default is CFL_TRUNCATE.", &
1701 units=
"nondim", default=cs%CFL_trunc)
1702 call get_param(param_file, mdl,
"CFL_TRUNCATE_RAMP_TIME", cs%truncRampTime, &
1703 "The time over which the CFL truncation value is ramped "//&
1704 "up at the beginning of the run.", &
1705 units=
"s", default=0.)
1706 cs%CFL_truncE = cs%CFL_trunc
1707 call get_param(param_file, mdl,
"CFL_TRUNCATE_START", cs%CFL_truncS, &
1708 "The start value of the truncation CFL number used when "//&
1709 "ramping up CFL_TRUNC.", &
1710 units=
"nondim", default=0.)
1711 call get_param(param_file, mdl,
"STOKES_MIXING_COMBINED", cs%StokesMixing, &
1712 "Flag to use Stokes drift Mixing via the Lagrangian "//&
1713 " current (Eulerian plus Stokes drift). "//&
1714 " Still needs work and testing, so not recommended for use.",&
1725 if (cs%StokesMixing)
then
1726 call mom_error(fatal,
"Stokes mixing requires user intervention in the code.\n"//&
1727 " Model now exiting. See MOM_vert_friction.F90 for \n"//&
1728 " details (search 'BGR 04/04/2018' to locate comment).")
1730 call get_param(param_file, mdl,
"VEL_UNDERFLOW", cs%vel_underflow, &
1731 "A negligibly small velocity magnitude below which velocity "//&
1732 "components are set to 0. A reasonable value might be "//&
1733 "1e-30 m/s, which is less than an Angstrom divided by "//&
1734 "the age of the universe.", units=
"m s-1", default=0.0)
1736 alloc_(cs%a_u(isdb:iedb,jsd:jed,nz+1)) ; cs%a_u(:,:,:) = 0.0
1737 alloc_(cs%h_u(isdb:iedb,jsd:jed,nz)) ; cs%h_u(:,:,:) = 0.0
1738 alloc_(cs%a_v(isd:ied,jsdb:jedb,nz+1)) ; cs%a_v(:,:,:) = 0.0
1739 alloc_(cs%h_v(isd:ied,jsdb:jedb,nz)) ; cs%h_v(:,:,:) = 0.0
1741 cs%id_Kv_slow = register_diag_field(
'ocean_model',
'Kv_slow', diag%axesTi, time, &
1742 'Slow varying vertical viscosity',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
1744 cs%id_Kv_u = register_diag_field(
'ocean_model',
'Kv_u', diag%axesCuL, time, &
1745 'Total vertical viscosity at u-points',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
1747 cs%id_Kv_v = register_diag_field(
'ocean_model',
'Kv_v', diag%axesCvL, time, &
1748 'Total vertical viscosity at v-points',
'm2 s-1', conversion=us%Z2_T_to_m2_s)
1750 cs%id_au_vv = register_diag_field(
'ocean_model',
'au_visc', diag%axesCui, time, &
1751 'Zonal Viscous Vertical Coupling Coefficient',
'm s-1', conversion=us%Z_to_m*us%s_to_T)
1753 cs%id_av_vv = register_diag_field(
'ocean_model',
'av_visc', diag%axesCvi, time, &
1754 'Meridional Viscous Vertical Coupling Coefficient',
'm s-1', conversion=us%Z_to_m*us%s_to_T)
1756 cs%id_h_u = register_diag_field(
'ocean_model',
'Hu_visc', diag%axesCuL, time, &
1757 'Thickness at Zonal Velocity Points for Viscosity', thickness_units)
1759 cs%id_h_v = register_diag_field(
'ocean_model',
'Hv_visc', diag%axesCvL, time, &
1760 'Thickness at Meridional Velocity Points for Viscosity', thickness_units)
1762 cs%id_hML_u = register_diag_field(
'ocean_model',
'HMLu_visc', diag%axesCu1, time, &
1763 'Mixed Layer Thickness at Zonal Velocity Points for Viscosity', thickness_units)
1765 cs%id_hML_v = register_diag_field(
'ocean_model',
'HMLv_visc', diag%axesCv1, time, &
1766 'Mixed Layer Thickness at Meridional Velocity Points for Viscosity', thickness_units)
1768 cs%id_du_dt_visc = register_diag_field(
'ocean_model',
'du_dt_visc', diag%axesCuL, &
1769 time,
'Zonal Acceleration from Vertical Viscosity',
'm s-2')
1770 if (cs%id_du_dt_visc > 0)
call safe_alloc_ptr(adp%du_dt_visc,isdb,iedb,jsd,jed,nz)
1771 cs%id_dv_dt_visc = register_diag_field(
'ocean_model',
'dv_dt_visc', diag%axesCvL, &
1772 time,
'Meridional Acceleration from Vertical Viscosity',
'm s-2')
1773 if (cs%id_dv_dt_visc > 0)
call safe_alloc_ptr(adp%dv_dt_visc,isd,ied,jsdb,jedb,nz)
1775 cs%id_taux_bot = register_diag_field(
'ocean_model',
'taux_bot', diag%axesCu1, &
1776 time,
'Zonal Bottom Stress from Ocean to Earth',
'Pa', &
1777 conversion=us%Z_to_m)
1778 cs%id_tauy_bot = register_diag_field(
'ocean_model',
'tauy_bot', diag%axesCv1, &
1779 time,
'Meridional Bottom Stress from Ocean to Earth',
'Pa', &
1780 conversion=us%Z_to_m)
1782 if ((len_trim(cs%u_trunc_file) > 0) .or. (len_trim(cs%v_trunc_file) > 0)) &
1783 call pointaccel_init(mis, time, g, param_file, diag, dirs, cs%PointAccel_CSp)
1785 end subroutine vertvisc_init
1790 subroutine updatecfltruncationvalue(Time, CS, activate)
1791 type(time_type),
target,
intent(in) :: time
1793 logical,
optional,
intent(in) :: activate
1797 real :: deltatime, wghta
1798 character(len=12) :: msg
1800 if (cs%truncRampTime==0.)
return
1804 if (
present(activate))
then
1806 cs%rampStartTime = time
1807 cs%CFLrampingIsActivated = .true.
1810 if (.not.cs%CFLrampingIsActivated)
return
1811 deltatime = max( 0., time_type_to_real( time - cs%rampStartTime ) )
1812 if (deltatime >= cs%truncRampTime)
then
1813 cs%CFL_trunc = cs%CFL_truncE
1814 cs%truncRampTime = 0.
1816 wghta = min( 1., deltatime / cs%truncRampTime )
1819 wghta = 1. - ( (1. - wghta)**2 )
1820 cs%CFL_trunc = cs%CFL_truncS + wghta * ( cs%CFL_truncE - cs%CFL_truncS )
1822 write(msg(1:12),
'(es12.3)') cs%CFL_trunc
1823 call mom_error(note,
"MOM_vert_friction: updateCFLtruncationValue set CFL"// &
1824 " limit to "//trim(msg))
1825 end subroutine updatecfltruncationvalue
1828 subroutine vertvisc_end(CS)
1832 dealloc_(cs%a_u) ; dealloc_(cs%h_u)
1833 dealloc_(cs%a_v) ; dealloc_(cs%h_v)
1834 if (
associated(cs%a1_shelf_u))
deallocate(cs%a1_shelf_u)
1835 if (
associated(cs%a1_shelf_v))
deallocate(cs%a1_shelf_v)
1837 end subroutine vertvisc_end