6 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
10 use mom_domains,
only : sum_across_pes, max_across_pes
21 implicit none ;
private
23 #include <MOM_memory.h>
26 public tracer_advect_init
27 public tracer_advect_end
37 type(group_pass_type) :: pass_uhr_vhr_t_hprev
41 integer :: id_clock_advect
42 integer :: id_clock_pass
43 integer :: id_clock_sync
50 subroutine advect_tracer(h_end, uhtr, vhtr, OBC, dt, G, GV, US, CS, Reg, &
51 h_prev_opt, max_iter_in, x_first_in, uhr_out, vhr_out, h_out)
54 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
56 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
58 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
61 real,
intent(in) :: dt
65 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
66 optional,
intent(in) :: h_prev_opt
67 integer,
optional,
intent(in) :: max_iter_in
68 logical,
optional,
intent(in) :: x_first_in
70 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
71 optional,
intent(out) :: uhr_out
73 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
74 optional,
intent(out) :: vhr_out
76 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
77 optional,
intent(out) :: h_out
80 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
82 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)) :: &
84 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)) :: &
86 real :: uh_neglect(szib_(g),szj_(g))
87 real :: vh_neglect(szi_(g),szjb_(g))
92 logical :: domore_u(szj_(g),szk_(g))
93 logical :: domore_v(szjb_(g),szk_(g))
97 integer :: domore_k(szk_(g))
100 integer :: i, j, k, m, is, ie, js, je, isd, ied, jsd, jed, nz, itt, ntr, do_any
101 integer :: isv, iev, jsv, jev
102 integer :: isdb, iedb, jsdb, jedb
104 domore_u(:,:) = .false.
105 domore_v(:,:) = .false.
106 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
107 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
108 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
109 landvolfill = 1.0e-20
112 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_tracer_advect: "// &
113 "tracer_advect_init must be called before advect_tracer.")
114 if (.not.
associated(reg))
call mom_error(fatal,
"MOM_tracer_advect: "// &
115 "register_tracer must be called before advect_tracer.")
116 if (reg%ntr==0)
return
117 call cpu_clock_begin(id_clock_advect)
118 x_first = (mod(g%first_direction,2) == 0)
121 if (cs%usePPM .and. .not. cs%useHuynh) stencil = 3
124 do m=1,ntr ; tr(m) = reg%Tr(m) ;
enddo
127 max_iter = 2*int(ceiling(dt/cs%dt)) + 1
129 if (
present(max_iter_in)) max_iter = max_iter_in
130 if (
present(x_first_in)) x_first = x_first_in
131 call cpu_clock_begin(id_clock_pass)
137 call cpu_clock_end(id_clock_pass)
147 do j=jsd,jed ;
do i=isdb,iedb ; uhr(i,j,k) = 0.0 ;
enddo ;
enddo
148 do j=jsdb,jedb ;
do i=isd,ied ; vhr(i,j,k) = 0.0 ;
enddo ;
enddo
149 do j=jsd,jed ;
do i=isd,ied ; hprev(i,j,k) = 0.0 ;
enddo ;
enddo
152 do j=js,je ;
do i=is-1,ie ; uhr(i,j,k) = uhtr(i,j,k) ;
enddo ;
enddo
153 do j=js-1,je ;
do i=is,ie ; vhr(i,j,k) = vhtr(i,j,k) ;
enddo ;
enddo
154 if (.not.
present(h_prev_opt))
then
158 do i=is,ie ;
do j=js,je
159 hprev(i,j,k) = max(0.0, g%areaT(i,j)*h_end(i,j,k) + &
160 ((uhr(i,j,k) - uhr(i-1,j,k)) + (vhr(i,j,k) - vhr(i,j-1,k))))
164 hprev(i,j,k) = hprev(i,j,k) + &
165 max(0.0, 1.0e-13*hprev(i,j,k) - g%areaT(i,j)*h_end(i,j,k))
168 do i=is,ie ;
do j=js,je
169 hprev(i,j,k) = h_prev_opt(i,j,k)
176 do j=jsd,jed ;
do i=isd,ied-1
177 uh_neglect(i,j) = gv%H_subroundoff * min(g%areaT(i,j), g%areaT(i+1,j))
180 do j=jsd,jed-1 ;
do i=isd,ied
181 vh_neglect(i,j) = gv%H_subroundoff * min(g%areaT(i,j), g%areaT(i,j+1))
187 if (
associated(tr(m)%ad_x))
then
188 do k=1,nz ;
do j=jsd,jed ;
do i=isd,ied
189 tr(m)%ad_x(i,j,k) = 0.0
190 enddo ;
enddo ;
enddo
192 if (
associated(tr(m)%ad_y))
then
193 do k=1,nz ;
do j=jsd,jed ;
do i=isd,ied
194 tr(m)%ad_y(i,j,k) = 0.0
195 enddo ;
enddo ;
enddo
197 if (
associated(tr(m)%advection_xy))
then
198 do k=1,nz ;
do j=jsd,jed ;
do i=isd,ied
199 tr(m)%advection_xy(i,j,k) = 0.0
200 enddo ;
enddo ;
enddo
202 if (
associated(tr(m)%ad2d_x))
then
203 do j=jsd,jed ;
do i=isd,ied ; tr(m)%ad2d_x(i,j) = 0.0 ;
enddo ;
enddo
205 if (
associated(tr(m)%ad2d_y))
then
206 do j=jsd,jed ;
do i=isd,ied ; tr(m)%ad2d_y(i,j) = 0.0 ;
enddo ;
enddo
211 isv = is ; iev = ie ; jsv = js ; jev = je
215 if (isv > is-stencil)
then
216 call do_group_pass(cs%pass_uhr_vhr_t_hprev, g%Domain, clock=id_clock_pass)
218 nsten_halo = min(is-isd,ied-ie,js-jsd,jed-je)/stencil
219 isv = is-nsten_halo*stencil ; jsv = js-nsten_halo*stencil
220 iev = ie+nsten_halo*stencil ; jev = je+nsten_halo*stencil
223 if ((nsten_halo > 1) .or. (itt==1))
then
225 do k=1,nz ;
if (domore_k(k) > 0)
then
226 do j=jsv,jev ;
if (.not.domore_u(j,k))
then
227 do i=isv+stencil-1,iev-stencil;
if (uhr(i,j,k) /= 0.0)
then
228 domore_u(j,k) = .true. ;
exit
231 do j=jsv+stencil-1,jev-stencil ;
if (.not.domore_v(j,k))
then
232 do i=isv+stencil,iev-stencil;
if (vhr(i,j,k) /= 0.0)
then
233 domore_v(j,k) = .true. ;
exit
240 do j=jsv,jev ;
if (domore_u(j,k)) domore_k(k) = 1 ;
enddo
241 do j=jsv+stencil-1,jev-stencil ;
if (domore_v(j,k)) domore_k(k) = 1 ;
enddo
248 isv = isv + stencil ; iev = iev - stencil
249 jsv = jsv + stencil ; jev = jev - stencil
262 do k=1,nz ;
if (domore_k(k) > 0)
then
264 call advect_x(tr, hprev, uhr, uh_neglect, obc, domore_u, ntr, idt, &
265 isv, iev, jsv-stencil, jev+stencil, k, g, gv, us, cs%usePPM, cs%useHuynh)
269 do k=1,nz ;
if (domore_k(k) > 0)
then
271 call advect_y(tr, hprev, vhr, vh_neglect, obc, domore_v, ntr, idt, &
272 isv, iev, jsv, jev, k, g, gv, us, cs%usePPM, cs%useHuynh)
276 do j=jsv-stencil,jev+stencil ;
if (domore_u(j,k)) domore_k(k) = 1 ;
enddo
277 do j=jsv-1,jev ;
if (domore_v(j,k)) domore_k(k) = 1 ;
enddo
284 do k=1,nz ;
if (domore_k(k) > 0)
then
286 call advect_y(tr, hprev, vhr, vh_neglect, obc, domore_v, ntr, idt, &
287 isv-stencil, iev+stencil, jsv, jev, k, g, gv, us, cs%usePPM, cs%useHuynh)
291 do k=1,nz ;
if (domore_k(k) > 0)
then
293 call advect_x(tr, hprev, uhr, uh_neglect, obc, domore_u, ntr, idt, &
294 isv, iev, jsv, jev, k, g, gv, us, cs%usePPM, cs%useHuynh)
298 do j=jsv,jev ;
if (domore_u(j,k)) domore_k(k) = 1 ;
enddo
299 do j=jsv-1,jev ;
if (domore_v(j,k)) domore_k(k) = 1 ;
enddo
307 if (itt >= max_iter)
then
312 if (isv > is-stencil)
then
314 call cpu_clock_begin(id_clock_sync)
315 call sum_across_pes(domore_k(:), nz)
316 call cpu_clock_end(id_clock_sync)
317 do k=1,nz ; do_any = do_any + domore_k(k) ;
enddo
318 if (do_any == 0)
then
326 if (
present(uhr_out)) uhr_out(:,:,:) = uhr(:,:,:)
327 if (
present(vhr_out)) vhr_out(:,:,:) = vhr(:,:,:)
328 if (
present(h_out)) h_out(:,:,:) = hprev(:,:,:)
330 call cpu_clock_end(id_clock_advect)
332 end subroutine advect_tracer
337 subroutine advect_x(Tr, hprev, uhr, uh_neglect, OBC, domore_u, ntr, Idt, &
338 is, ie, js, je, k, G, GV, US, usePPM, useHuynh)
341 type(
tracer_type),
dimension(ntr),
intent(inout) :: Tr
342 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: hprev
344 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhr
346 real,
dimension(SZIB_(G),SZJ_(G)),
intent(in) :: uh_neglect
349 logical,
dimension(SZJ_(G),SZK_(G)),
intent(inout) :: domore_u
351 real,
intent(in) :: Idt
352 integer,
intent(in) :: ntr
353 integer,
intent(in) :: is
354 integer,
intent(in) :: ie
355 integer,
intent(in) :: js
356 integer,
intent(in) :: je
357 integer,
intent(in) :: k
359 logical,
intent(in) :: usePPM
360 logical,
intent(in) :: useHuynh
363 real,
dimension(SZI_(G),ntr) :: &
365 real,
dimension(SZIB_(G),SZJ_(G),ntr) :: &
367 real,
dimension(SZI_(G),ntr) :: &
376 real :: uhh(SZIB_(G))
378 real,
dimension(SZIB_(G)) :: &
387 logical :: do_i(SZIB_(G),SZJ_(G))
389 integer :: i, j, m, n, i_up, stencil
390 real :: aR, aL, dMx, dMn, Tp, Tc, Tm, dA, mA, a6
391 real :: fac1,u_L_in,u_L_out
393 logical :: usePLMslope
394 logical,
dimension(SZJ_(G),SZK_(G)) :: domore_u_initial
398 domore_u_initial = domore_u
400 useplmslope = .not. (useppm .and. usehuynh)
403 if (useppm .and. .not. usehuynh) stencil = 2
405 min_h = 0.1*gv%Angstrom_H
407 h_neglect = gv%H_subroundoff
409 do i=is-1,ie ; cfl(i) = 0.0 ;
enddo
411 do j=js,je ;
if (domore_u(j,k))
then
412 domore_u(j,k) = .false.
415 if (useplmslope)
then
416 do m=1,ntr ;
do i=is-stencil,ie+stencil
431 tp = tr(m)%t(i+1,j,k) ; tc = tr(m)%t(i,j,k) ; tm = tr(m)%t(i-1,j,k)
432 dmx = max( tp, tc, tm ) - tc
433 dmn= tc - min( tp, tc, tm )
434 slope_x(i,m) = g%mask2dCu(i,j)*g%mask2dCu(i-1,j) * &
435 sign( min(0.5*abs(tp-tm), 2.0*dmx, 2.0*dmn), tp-tm )
442 t_tmp(i,m) = tr(m)%t(i,j,k)
446 if (
associated(obc))
then ;
if (obc%OBC_pe)
then
447 do n=1,obc%number_of_segments
448 segment=>obc%segment(n)
449 if (.not.
associated(segment%tr_Reg)) cycle
450 if (segment%is_E_or_W)
then
451 if (j>=segment%HI%jsd .and. j<=segment%HI%jed)
then
454 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
455 if (segment%direction == obc_direction_w)
then
456 t_tmp(i,m) = segment%tr_Reg%Tr(m)%tres(i,j,k)
458 t_tmp(i+1,m) = segment%tr_Reg%Tr(m)%tres(i,j,k)
461 if (segment%direction == obc_direction_w)
then
462 t_tmp(i,m) = segment%tr_Reg%Tr(m)%OBC_inflow_conc
464 t_tmp(i+1,m) = segment%tr_Reg%Tr(m)%OBC_inflow_conc
469 do i=segment%HI%IsdB-1,segment%HI%IsdB+1
470 tp = t_tmp(i+1,m) ; tc = t_tmp(i,m) ; tm = t_tmp(i-1,m)
471 dmx = max( tp, tc, tm ) - tc
472 dmn= tc - min( tp, tc, tm )
473 slope_x(i,m) = g%mask2dCu(i,j)*g%mask2dCu(i-1,j) * &
474 sign( min(0.5*abs(tp-tm), 2.0*dmx, 2.0*dmn), tp-tm )
489 if ((uhr(i,j,k) == 0.0) .or. &
490 ((uhr(i,j,k) < 0.0) .and. (hprev(i+1,j,k) <= tiny_h)) .or. &
491 ((uhr(i,j,k) > 0.0) .and. (hprev(i,j,k) <= tiny_h)) )
then
494 elseif (uhr(i,j,k) < 0.0)
then
495 hup = hprev(i+1,j,k) - g%areaT(i+1,j)*min_h
496 hlos = max(0.0, uhr(i+1,j,k))
497 if ((((hup - hlos) + uhr(i,j,k)) < 0.0) .and. &
498 ((0.5*hup + uhr(i,j,k)) < 0.0))
then
499 uhh(i) = min(-0.5*hup, -hup+hlos, 0.0)
500 domore_u(j,k) = .true.
504 cfl(i) = - uhh(i) / (hprev(i+1,j,k))
506 hup = hprev(i,j,k) - g%areaT(i,j)*min_h
507 hlos = max(0.0, -uhr(i-1,j,k))
508 if ((((hup - hlos) - uhr(i,j,k)) < 0.0) .and. &
509 ((0.5*hup - uhr(i,j,k)) < 0.0))
then
510 uhh(i) = max(0.5*hup, hup-hlos, 0.0)
511 domore_u(j,k) = .true.
515 cfl(i) = uhh(i) / (hprev(i,j,k))
521 do m=1,ntr ;
do i=is-1,ie
523 if (uhh(i) >= 0.0)
then
530 tp = t_tmp(i_up+1,m) ; tc = t_tmp(i_up,m) ; tm = t_tmp(i_up-1,m)
533 al = ( 5.*tc + ( 2.*tm - tp ) )/6.
534 al = max( min(tc,tm), al) ; al = min( max(tc,tm), al)
535 ar = ( 5.*tc + ( 2.*tp - tm ) )/6.
536 ar = max( min(tc,tp), ar) ; ar = min( max(tc,tp), ar)
538 al = 0.5 * ((tm + tc) + (slope_x(i_up-1,m) - slope_x(i_up,m)) / 3.)
539 ar = 0.5 * ((tc + tp) + (slope_x(i_up,m) - slope_x(i_up+1,m)) / 3.)
542 da = ar - al ; ma = 0.5*( ar + al )
543 if (g%mask2dCu(i_up,j)*g%mask2dCu(i_up-1,j)*(tp-tc)*(tc-tm) <= 0.)
then
545 elseif ( da*(tc-ma) > (da*da)/6. )
then
547 elseif ( da*(tc-ma) < - (da*da)/6. )
then
551 a6 = 6.*tc - 3. * (ar + al)
553 if (uhh(i) >= 0.0)
then
554 flux_x(i,j,m) = uhh(i)*( ar - 0.5 * cfl(i) * ( &
555 ( ar - al ) - a6 * ( 1. - 2./3. * cfl(i) ) ) )
557 flux_x(i,j,m) = uhh(i)*( al + 0.5 * cfl(i) * ( &
558 ( ar - al ) + a6 * ( 1. - 2./3. * cfl(i) ) ) )
562 do m=1,ntr ;
do i=is-1,ie
563 if (uhh(i) >= 0.0)
then
570 flux_x(i,j,m) = uhh(i)*( tc + 0.5 * slope_x(i,m) * ( 1. - cfl(i) ) )
578 flux_x(i,j,m) = uhh(i)*( tc - 0.5 * slope_x(i+1,m) * ( 1. - cfl(i) ) )
583 if (
associated(obc))
then ;
if (obc%OBC_pe)
then
584 if (obc%specified_u_BCs_exist_globally .or. obc%open_u_BCs_exist_globally)
then
585 do n=1,obc%number_of_segments
586 segment=>obc%segment(n)
587 if (.not.
associated(segment%tr_Reg)) cycle
588 if (segment%is_E_or_W)
then
589 if (j>=segment%HI%jsd .and. j<=segment%HI%jed)
then
593 if ((uhr(i,j,k) > 0.0) .and. (segment%direction == obc_direction_w) .or. &
594 (uhr(i,j,k) < 0.0) .and. (segment%direction == obc_direction_e))
then
598 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
599 flux_x(i,j,m) = uhh(i)*segment%tr_Reg%Tr(m)%tres(i,j,k)
600 else ; flux_x(i,j,m) = uhh(i)*segment%tr_Reg%Tr(m)%OBC_inflow_conc ;
endif
608 if (obc%open_u_BCs_exist_globally)
then
609 do n=1,obc%number_of_segments
610 segment=>obc%segment(n)
612 if (segment%is_E_or_W .and. (j >= segment%HI%jsd .and. j<= segment%HI%jed))
then
613 if (segment%specified) cycle
614 if (.not.
associated(segment%tr_Reg)) cycle
617 if ((uhr(i,j,k) > 0.0) .and. (g%mask2dT(i,j) < 0.5) .or. &
618 (uhr(i,j,k) < 0.0) .and. (g%mask2dT(i+1,j) < 0.5))
then
621 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
622 flux_x(i,j,m) = uhh(i)*segment%tr_Reg%Tr(m)%tres(i,j,k)
623 else; flux_x(i,j,m) = uhh(i)*segment%tr_Reg%Tr(m)%OBC_inflow_conc;
endif
634 uhr(i,j,k) = uhr(i,j,k) - uhh(i)
635 if (abs(uhr(i,j,k)) < uh_neglect(i,j)) uhr(i,j,k) = 0.0
638 if ((uhh(i) /= 0.0) .or. (uhh(i-1) /= 0.0))
then
640 hlst(i) = hprev(i,j,k)
641 hprev(i,j,k) = hprev(i,j,k) - (uhh(i) - uhh(i-1))
642 if (hprev(i,j,k) <= 0.0)
then ; do_i(i,j) = .false.
643 elseif (hprev(i,j,k) < h_neglect*g%areaT(i,j))
then
644 hlst(i) = hlst(i) + (h_neglect*g%areaT(i,j) - hprev(i,j,k))
645 ihnew(i) = 1.0 / (h_neglect*g%areaT(i,j))
646 else ; ihnew(i) = 1.0 / hprev(i,j,k) ;
endif
658 if (ihnew(i) > 0.0)
then
659 tr(m)%t(i,j,k) = (tr(m)%t(i,j,k) * hlst(i) - &
660 (flux_x(i,j,m) - flux_x(i-1,j,m))) * ihnew(i)
666 if (
associated(tr(m)%ad_x))
then ;
do i=is,ie ;
if (do_i(i,j))
then
667 tr(m)%ad_x(i,j,k) = tr(m)%ad_x(i,j,k) + flux_x(i,j,m)*idt
668 endif ;
enddo ;
endif
672 if (
associated(tr(m)%advection_xy))
then
673 do i=is,ie ;
if (do_i(i,j))
then
674 tr(m)%advection_xy(i,j,k) = tr(m)%advection_xy(i,j,k) - (flux_x(i,j,m) - flux_x(i-1,j,m)) * &
689 do j=js,je ;
if (domore_u_initial(j,k))
then
691 if (
associated(tr(m)%ad2d_x))
then ;
do i=is,ie ;
if (do_i(i,j))
then
692 tr(m)%ad2d_x(i,j) = tr(m)%ad2d_x(i,j) + flux_x(i,j,m)*idt
693 endif ;
enddo ;
endif
698 end subroutine advect_x
702 subroutine advect_y(Tr, hprev, vhr, vh_neglect, OBC, domore_v, ntr, Idt, &
703 is, ie, js, je, k, G, GV, US, usePPM, useHuynh)
706 type(
tracer_type),
dimension(ntr),
intent(inout) :: Tr
707 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: hprev
709 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhr
711 real,
dimension(SZI_(G),SZJB_(G)),
intent(inout) :: vh_neglect
714 logical,
dimension(SZJB_(G),SZK_(G)),
intent(inout) :: domore_v
716 real,
intent(in) :: Idt
717 integer,
intent(in) :: ntr
718 integer,
intent(in) :: is
719 integer,
intent(in) :: ie
720 integer,
intent(in) :: js
721 integer,
intent(in) :: je
722 integer,
intent(in) :: k
724 logical,
intent(in) :: usePPM
725 logical,
intent(in) :: useHuynh
728 real,
dimension(SZI_(G),ntr,SZJ_(G)) :: &
730 real,
dimension(SZI_(G),ntr,SZJB_(G)) :: &
732 real,
dimension(SZI_(G),ntr,SZJB_(G)) :: &
736 real :: vhh(SZI_(G),SZJB_(G))
742 real,
dimension(SZIB_(G)) :: &
751 logical :: do_j_tr(SZJ_(G))
752 logical :: do_i(SZIB_(G), SZJ_(G))
754 integer :: i, j, j2, m, n, j_up, stencil
755 real :: aR, aL, dMx, dMn, Tp, Tc, Tm, dA, mA, a6
756 real :: fac1,v_L_in,v_L_out
758 logical :: usePLMslope
760 useplmslope = .not. (useppm .and. usehuynh)
763 if (useppm .and. .not. usehuynh) stencil = 2
765 min_h = 0.1*gv%Angstrom_H
767 h_neglect = gv%H_subroundoff
780 do j=js-1,je ;
if (domore_v(j,k))
then ;
do j2=1-stencil,stencil ; do_j_tr(j+j2) = .true. ;
enddo ;
endif ;
enddo
784 if (useplmslope)
then
785 do j=js-stencil,je+stencil ;
if (do_j_tr(j))
then ;
do m=1,ntr ;
do i=is,ie
800 tp = tr(m)%t(i,j+1,k) ; tc = tr(m)%t(i,j,k) ; tm = tr(m)%t(i,j-1,k)
801 dmx = max( tp, tc, tm ) - tc
802 dmn= tc - min( tp, tc, tm )
803 slope_y(i,m,j) = g%mask2dCv(i,j)*g%mask2dCv(i,j-1) * &
804 sign( min(0.5*abs(tp-tm), 2.0*dmx, 2.0*dmn), tp-tm )
805 enddo ;
enddo ;
endif ;
enddo
811 do j=g%jsd,g%jed ;
do m=1,ntr ;
do i=g%isd,g%ied
812 t_tmp(i,m,j) = tr(m)%t(i,j,k)
813 enddo ;
enddo ;
enddo
816 if (
associated(obc))
then ;
if (obc%OBC_pe)
then
817 do n=1,obc%number_of_segments
818 segment=>obc%segment(n)
819 if (.not.
associated(segment%tr_Reg)) cycle
821 if (segment%is_N_or_S)
then
822 if (i>=segment%HI%isd .and. i<=segment%HI%ied)
then
825 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
826 if (segment%direction == obc_direction_s)
then
827 t_tmp(i,m,j) = segment%tr_Reg%Tr(m)%tres(i,j,k)
829 t_tmp(i,m,j+1) = segment%tr_Reg%Tr(m)%tres(i,j,k)
832 if (segment%direction == obc_direction_s)
then
833 t_tmp(i,m,j) = segment%tr_Reg%Tr(m)%OBC_inflow_conc
835 t_tmp(i,m,j+1) = segment%tr_Reg%Tr(m)%OBC_inflow_conc
840 do j=segment%HI%JsdB-1,segment%HI%JsdB+1
841 tp = t_tmp(i,m,j+1) ; tc = t_tmp(i,m,j) ; tm = t_tmp(i,m,j-1)
842 dmx = max( tp, tc, tm ) - tc
843 dmn= tc - min( tp, tc, tm )
844 slope_y(i,m,j) = g%mask2dCv(i,j)*g%mask2dCv(i,j-1) * &
845 sign( min(0.5*abs(tp-tm), 2.0*dmx, 2.0*dmn), tp-tm )
858 do j=js-1,je ;
if (domore_v(j,k))
then
859 domore_v(j,k) = .false.
862 if ((vhr(i,j,k) == 0.0) .or. &
863 ((vhr(i,j,k) < 0.0) .and. (hprev(i,j+1,k) <= tiny_h)) .or. &
864 ((vhr(i,j,k) > 0.0) .and. (hprev(i,j,k) <= tiny_h)) )
then
867 elseif (vhr(i,j,k) < 0.0)
then
868 hup = hprev(i,j+1,k) - g%areaT(i,j+1)*min_h
869 hlos = max(0.0, vhr(i,j+1,k))
870 if ((((hup - hlos) + vhr(i,j,k)) < 0.0) .and. &
871 ((0.5*hup + vhr(i,j,k)) < 0.0))
then
872 vhh(i,j) = min(-0.5*hup, -hup+hlos, 0.0)
873 domore_v(j,k) = .true.
875 vhh(i,j) = vhr(i,j,k)
877 cfl(i) = - vhh(i,j) / hprev(i,j+1,k)
879 hup = hprev(i,j,k) - g%areaT(i,j)*min_h
880 hlos = max(0.0, -vhr(i,j-1,k))
881 if ((((hup - hlos) - vhr(i,j,k)) < 0.0) .and. &
882 ((0.5*hup - vhr(i,j,k)) < 0.0))
then
883 vhh(i,j) = max(0.5*hup, hup-hlos, 0.0)
884 domore_v(j,k) = .true.
886 vhh(i,j) = vhr(i,j,k)
888 cfl(i) = vhh(i,j) / hprev(i,j,k)
893 do m=1,ntr ;
do i=is,ie
895 if (vhh(i,j) >= 0.0)
then
902 tp = t_tmp(i,m,j_up+1) ; tc = t_tmp(i,m,j_up) ; tm = t_tmp(i,m,j_up-1)
905 al = ( 5.*tc + ( 2.*tm - tp ) )/6.
906 al = max( min(tc,tm), al) ; al = min( max(tc,tm), al)
907 ar = ( 5.*tc + ( 2.*tp - tm ) )/6.
908 ar = max( min(tc,tp), ar) ; ar = min( max(tc,tp), ar)
910 al = 0.5 * ((tm + tc) + (slope_y(i,m,j_up-1) - slope_y(i,m,j_up)) / 3.)
911 ar = 0.5 * ((tc + tp) + (slope_y(i,m,j_up) - slope_y(i,m,j_up+1)) / 3.)
914 da = ar - al ; ma = 0.5*( ar + al )
915 if (g%mask2dCv(i,j_up)*g%mask2dCv(i,j_up-1)*(tp-tc)*(tc-tm) <= 0.)
then
917 elseif ( da*(tc-ma) > (da*da)/6. )
then
919 elseif ( da*(tc-ma) < - (da*da)/6. )
then
923 a6 = 6.*tc - 3. * (ar + al)
925 if (vhh(i,j) >= 0.0)
then
926 flux_y(i,m,j) = vhh(i,j)*( ar - 0.5 * cfl(i) * ( &
927 ( ar - al ) - a6 * ( 1. - 2./3. * cfl(i) ) ) )
929 flux_y(i,m,j) = vhh(i,j)*( al + 0.5 * cfl(i) * ( &
930 ( ar - al ) + a6 * ( 1. - 2./3. * cfl(i) ) ) )
934 do m=1,ntr ;
do i=is,ie
935 if (vhh(i,j) >= 0.0)
then
942 flux_y(i,m,j) = vhh(i,j)*( tc + 0.5 * slope_y(i,m,j) * ( 1. - cfl(i) ) )
950 flux_y(i,m,j) = vhh(i,j)*( tc - 0.5 * slope_y(i,m,j+1) * ( 1. - cfl(i) ) )
955 if (
associated(obc))
then ;
if (obc%OBC_pe)
then
956 if (obc%specified_v_BCs_exist_globally .or. obc%open_v_BCs_exist_globally)
then
957 do n=1,obc%number_of_segments
958 segment=>obc%segment(n)
959 if (.not. segment%specified) cycle
960 if (.not.
associated(segment%tr_Reg)) cycle
961 if (obc%segment(n)%is_N_or_S)
then
962 if (j >= segment%HI%JsdB .and. j<= segment%HI%JedB)
then
963 do i=segment%HI%isd,segment%HI%ied
966 if ((vhr(i,j,k) > 0.0) .and. (segment%direction == obc_direction_s) .or. &
967 (vhr(i,j,k) < 0.0) .and. (segment%direction == obc_direction_n))
then
968 vhh(i,j) = vhr(i,j,k)
970 if (
associated(segment%tr_Reg%Tr(m)%t))
then
971 flux_y(i,m,j) = vhh(i,j)*obc%segment(n)%tr_Reg%Tr(m)%tres(i,j,k)
972 else ; flux_y(i,m,j) = vhh(i,j)*obc%segment(n)%tr_Reg%Tr(m)%OBC_inflow_conc ;
endif
981 if (obc%open_v_BCs_exist_globally)
then
982 do n=1,obc%number_of_segments
983 segment=>obc%segment(n)
984 if (segment%specified) cycle
985 if (.not.
associated(segment%tr_Reg)) cycle
986 if (segment%is_N_or_S .and. (j >= segment%HI%JsdB .and. j<= segment%HI%JedB))
then
987 do i=segment%HI%isd,segment%HI%ied
989 if ((vhr(i,j,k) > 0.0) .and. (g%mask2dT(i,j) < 0.5) .or. &
990 (vhr(i,j,k) < 0.0) .and. (g%mask2dT(i,j+1) < 0.5))
then
991 vhh(i,j) = vhr(i,j,k)
993 if (
associated(segment%tr_Reg%Tr(m)%t))
then
994 flux_y(i,m,j) = vhh(i,j)*segment%tr_Reg%Tr(m)%tres(i,j,k)
995 else ; flux_y(i,m,j) = vhh(i,j)*segment%tr_Reg%Tr(m)%OBC_inflow_conc ;
endif
1005 do i=is,ie ; vhh(i,j) = 0.0 ;
enddo
1006 do m=1,ntr ;
do i=is,ie ; flux_y(i,m,j) = 0.0 ;
enddo ;
enddo
1009 do j=js-1,je ;
do i=is,ie
1010 vhr(i,j,k) = vhr(i,j,k) - vhh(i,j)
1011 if (abs(vhr(i,j,k)) < vh_neglect(i,j)) vhr(i,j,k) = 0.0
1016 do j=js,je ;
if (do_j_tr(j))
then
1018 if ((vhh(i,j) /= 0.0) .or. (vhh(i,j-1) /= 0.0))
then
1020 hlst(i) = hprev(i,j,k)
1021 hprev(i,j,k) = max(hprev(i,j,k) - (vhh(i,j) - vhh(i,j-1)), 0.0)
1022 if (hprev(i,j,k) <= 0.0)
then ; do_i(i,j) = .false.
1023 elseif (hprev(i,j,k) < h_neglect*g%areaT(i,j))
then
1024 hlst(i) = hlst(i) + (h_neglect*g%areaT(i,j) - hprev(i,j,k))
1025 ihnew(i) = 1.0 / (h_neglect*g%areaT(i,j))
1026 else ; ihnew(i) = 1.0 / hprev(i,j,k) ;
endif
1027 else ; do_i(i,j) = .false. ;
endif
1032 do i=is,ie ;
if (do_i(i,j))
then
1033 tr(m)%t(i,j,k) = (tr(m)%t(i,j,k) * hlst(i) - &
1034 (flux_y(i,m,j) - flux_y(i,m,j-1))) * ihnew(i)
1038 if (
associated(tr(m)%ad_y))
then ;
do i=is,ie ;
if (do_i(i,j))
then
1039 tr(m)%ad_y(i,j,k) = tr(m)%ad_y(i,j,k) + flux_y(i,m,j)*idt
1040 endif ;
enddo ;
endif
1044 if (
associated(tr(m)%advection_xy))
then
1045 do i=is,ie ;
if (do_i(i,j))
then
1046 tr(m)%advection_xy(i,j,k) = tr(m)%advection_xy(i,j,k) - (flux_y(i,m,j) - flux_y(i,m,j-1))* idt * &
1057 do j=js,je ;
if (do_j_tr(j))
then
1059 if (
associated(tr(m)%ad2d_y))
then ;
do i=is,ie ;
if (do_i(i,j))
then
1060 tr(m)%ad2d_y(i,j) = tr(m)%ad2d_y(i,j) + flux_y(i,m,j)*idt
1061 endif ;
enddo ;
endif
1066 end subroutine advect_y
1069 subroutine tracer_advect_init(Time, G, US, param_file, diag, CS)
1070 type(time_type),
target,
intent(in) :: time
1074 type(
diag_ctrl),
target,
intent(inout) :: diag
1077 integer,
save :: init_calls = 0
1080 # include "version_variable.h"
1081 character(len=40) :: mdl =
"MOM_tracer_advect"
1082 character(len=256) :: mesg
1084 if (
associated(cs))
then
1085 call mom_error(warning,
"tracer_advect_init called with associated control structure.")
1094 call get_param(param_file, mdl,
"DT", cs%dt, fail_if_missing=.true., &
1095 desc=
"The (baroclinic) dynamics time step.", units=
"s", scale=us%s_to_T)
1096 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false.)
1097 call get_param(param_file, mdl,
"TRACER_ADVECTION_SCHEME", mesg, &
1098 desc=
"The horizontal transport scheme for tracers:\n"//&
1099 " PLM - Piecewise Linear Method\n"//&
1100 " PPM:H3 - Piecewise Parabolic Method (Huyhn 3rd order)\n"// &
1101 " PPM - Piecewise Parabolic Method (Colella-Woodward)" &
1103 select case (trim(mesg))
1108 cs%useHuynh = .true.
1111 cs%useHuynh = .false.
1113 call mom_error(fatal,
"MOM_tracer_advect, tracer_advect_init: "//&
1114 "Unknown TRACER_ADVECTION_SCHEME = "//trim(mesg))
1117 id_clock_advect = cpu_clock_id(
'(Ocean advect tracer)', grain=clock_module)
1118 id_clock_pass = cpu_clock_id(
'(Ocean tracer halo updates)', grain=clock_routine)
1119 id_clock_sync = cpu_clock_id(
'(Ocean tracer global synch)', grain=clock_routine)
1121 end subroutine tracer_advect_init
1124 subroutine tracer_advect_end(CS)
1127 if (
associated(cs))
deallocate(cs)
1129 end subroutine tracer_advect_end