7 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
11 use mom_domains, only : sum_across_pes, max_across_pes
20 implicit none ;
private 22 #include <MOM_memory.h> 36 type(group_pass_type) :: pass_uhr_vhr_t_hprev
47 subroutine advect_tracer(h_end, uhtr, vhtr, OBC, dt, G, GV, CS, Reg, &
48 h_prev_opt, max_iter_in, x_first_in, uhr_out, vhr_out, h_out)
51 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_end
52 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: uhtr
53 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: vhtr
55 real,
intent(in) :: dt
58 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
optional :: h_prev_opt
59 integer,
optional :: max_iter_in
60 logical,
optional :: x_first_in
61 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
optional,
intent(out) :: uhr_out
62 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
optional,
intent(out) :: vhr_out
63 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
optional :: h_out
66 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
68 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)) :: &
70 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)) :: &
72 real :: uh_neglect(szib_(g),szj_(g))
73 real :: vh_neglect(szi_(g),szjb_(g))
78 logical :: domore_u(szj_(g),szk_(g))
79 logical :: domore_v(szjb_(g),szk_(g))
83 integer :: domore_k(szk_(g))
86 integer :: i, j, k, m, is, ie, js, je, isd, ied, jsd, jed, nz, itt, ntr, do_any
87 integer :: isv, iev, jsv, jev
88 integer :: IsdB, IedB, JsdB, JedB
90 domore_u(:,:) = .false.
91 domore_v(:,:) = .false.
92 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
93 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
94 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
98 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_tracer_advect: "// &
99 "tracer_advect_init must be called before advect_tracer.")
100 if (.not.
associated(reg))
call mom_error(fatal,
"MOM_tracer_advect: "// &
101 "register_tracer must be called before advect_tracer.")
102 if (reg%ntr==0)
return 104 x_first = (mod(g%first_direction,2) == 0)
107 if (cs%usePPM .and. .not. cs%useHuynh) stencil = 3
110 do m=1,ntr ; tr(m) = reg%Tr(m) ;
enddo 113 max_iter = 2*int(ceiling(dt/cs%dt)) + 1
115 if(
present(max_iter_in)) max_iter = max_iter_in
116 if(
present(x_first_in)) x_first = x_first_in
134 do j = jsd, jed;
do i = isdb, iedb; uhr(i,j,k) = 0.0;
enddo ;
enddo 135 do j = jsdb, jedb;
do i = isd, ied; vhr(i,j,k) = 0.0;
enddo ;
enddo 136 do j = jsd, jed;
do i = isd, ied; hprev(i,j,k) = 0.0;
enddo ;
enddo 139 do j=js,je ;
do i=is-1,ie ; uhr(i,j,k) = uhtr(i,j,k) ;
enddo ;
enddo 140 do j=js-1,je ;
do i=is,ie ; vhr(i,j,k) = vhtr(i,j,k) ;
enddo ;
enddo 141 if (.not.
present(h_prev_opt))
then 145 do i=is,ie ;
do j=js,je
146 hprev(i,j,k) = max(0.0, g%areaT(i,j)*h_end(i,j,k) + &
147 ((uhr(i,j,k) - uhr(i-1,j,k)) + (vhr(i,j,k) - vhr(i,j-1,k))))
151 hprev(i,j,k) = hprev(i,j,k) + &
152 max(0.0, 1.0e-13*hprev(i,j,k) - g%areaT(i,j)*h_end(i,j,k))
155 do i=is,ie ;
do j=js,je
156 hprev(i,j,k) = h_prev_opt(i,j,k);
163 do j=jsd,jed ;
do i=isd,ied-1
164 uh_neglect(i,j) = gv%H_subroundoff*min(g%areaT(i,j),g%areaT(i+1,j))
167 do j=jsd,jed-1 ;
do i=isd,ied
168 vh_neglect(i,j) = gv%H_subroundoff*min(g%areaT(i,j),g%areaT(i,j+1))
174 if (
associated(tr(m)%ad_x))
then 175 do k=1,nz ;
do j=jsd,jed ;
do i=isd,ied
176 tr(m)%ad_x(i,j,k) = 0.0
177 enddo ;
enddo ;
enddo 179 if (
associated(tr(m)%ad_y))
then 180 do k=1,nz ;
do j=jsd,jed ;
do i=isd,ied
181 tr(m)%ad_y(i,j,k) = 0.0
182 enddo ;
enddo ;
enddo 184 if (
associated(tr(m)%advection_xy))
then 185 do k=1,nz ;
do j=jsd,jed ;
do i=isd,ied
186 tr(m)%advection_xy(i,j,k) = 0.0
187 enddo ;
enddo ;
enddo 189 if (
associated(tr(m)%ad2d_x))
then 190 do j=jsd,jed ;
do i=isd,ied ; tr(m)%ad2d_x(i,j) = 0.0 ;
enddo ;
enddo 192 if (
associated(tr(m)%ad2d_y))
then 193 do j=jsd,jed ;
do i=isd,ied ; tr(m)%ad2d_y(i,j) = 0.0 ;
enddo ;
enddo 198 isv = is ; iev = ie ; jsv = js ; jev = je
202 if (isv > is-stencil)
then 207 nsten_halo = min(is-isd,ied-ie,js-jsd,jed-je)/stencil
208 isv = is-nsten_halo*stencil ; jsv = js-nsten_halo*stencil
209 iev = ie+nsten_halo*stencil ; jev = je+nsten_halo*stencil
212 if ((nsten_halo > 1) .or. (itt==1))
then 215 do k=1,nz ;
if (domore_k(k) > 0)
then 216 do j=jsv,jev ;
if (.not.domore_u(j,k))
then 217 do i=isv+stencil-1,iev-stencil;
if (uhr(i,j,k) /= 0.0)
then 218 domore_u(j,k) = .true. ;
exit 221 do j=jsv+stencil-1,jev-stencil ;
if (.not.domore_v(j,k))
then 222 do i=isv+stencil,iev-stencil;
if (vhr(i,j,k) /= 0.0)
then 223 domore_v(j,k) = .true. ;
exit 230 do j=jsv,jev ;
if (domore_u(j,k)) domore_k(k) = 1 ;
enddo 231 do j=jsv+stencil-1,jev-stencil ;
if (domore_v(j,k)) domore_k(k) = 1 ;
enddo 238 isv = isv + stencil ; iev = iev - stencil
239 jsv = jsv + stencil ; jev = jev - stencil
250 do k=1,nz ;
if (domore_k(k) > 0)
then 255 call advect_x(tr, hprev, uhr, uh_neglect, obc, domore_u, ntr, idt, &
256 isv, iev, jsv-stencil, jev+stencil, k, g, gv, cs%usePPM, cs%useHuynh)
259 call advect_y(tr, hprev, vhr, vh_neglect, obc, domore_v, ntr, idt, &
260 isv, iev, jsv, jev, k, g, gv, cs%usePPM, cs%useHuynh)
263 do j=jsv-stencil,jev+stencil ;
if (domore_u(j,k)) domore_k(k) = 1 ;
enddo 264 do j=jsv-1,jev ;
if (domore_v(j,k)) domore_k(k) = 1 ;
enddo 269 call advect_y(tr, hprev, vhr, vh_neglect, obc, domore_v, ntr, idt, &
270 isv-stencil, iev+stencil, jsv, jev, k, g, gv, cs%usePPM, cs%useHuynh)
273 call advect_x(tr, hprev, uhr, uh_neglect, obc, domore_u, ntr, idt, &
274 isv, iev, jsv, jev, k, g, gv, cs%usePPM, cs%useHuynh)
277 do j=jsv,jev ;
if (domore_u(j,k)) domore_k(k) = 1 ;
enddo 278 do j=jsv-1,jev ;
if (domore_v(j,k)) domore_k(k) = 1 ;
enddo 286 if (itt >= max_iter)
then 291 if (isv > is-stencil)
then 294 call sum_across_pes(domore_k(:), nz)
296 do k=1,nz ; do_any = do_any + domore_k(k) ;
enddo 297 if (do_any == 0)
then 305 if(
present(uhr_out)) uhr_out(:,:,:) = uhr(:,:,:)
306 if(
present(vhr_out)) vhr_out(:,:,:) = vhr(:,:,:)
307 if(
present(h_out)) h_out(:,:,:) = hprev(:,:,:)
316 subroutine advect_x(Tr, hprev, uhr, uh_neglect, OBC, domore_u, ntr, Idt, &
317 is, ie, js, je, k, G, GV, usePPM, useHuynh)
320 type(
tracer_type),
dimension(ntr),
intent(inout) :: Tr
321 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: hprev
322 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhr
323 real,
dimension(SZIB_(G),SZJ_(G)),
intent(inout) :: uh_neglect
325 logical,
dimension(SZJ_(G),SZK_(G)),
intent(inout) :: domore_u
326 real,
intent(in) :: Idt
327 integer,
intent(in) :: ntr, is, ie, js, je,k
328 logical,
intent(in) :: usePPM, useHuynh
330 real,
dimension(SZI_(G),ntr) :: &
333 real,
dimension(SZIB_(G),ntr) :: &
341 real :: uhh(szib_(g))
343 real,
dimension(SZIB_(G)) :: &
350 logical :: do_i(szib_(g))
352 integer :: i, j, m, n, i_up, stencil
353 real :: aR, aL, dMx, dMn, Tp, Tc, Tm, dA, mA, a6
354 logical :: usePLMslope
356 useplmslope = .not. (useppm .and. usehuynh)
359 if (useppm .and. .not. usehuynh) stencil = 2
361 min_h = 0.1*gv%Angstrom
362 h_neglect = gv%H_subroundoff
365 do i=is-1,ie ; cfl(i) = 0.0 ;
enddo 367 do j=js,je ;
if (domore_u(j,k))
then 368 domore_u(j,k) = .false.
372 if (useplmslope)
then 373 do m=1,ntr ;
do i=is-stencil,ie+stencil
388 tp = tr(m)%t(i+1,j,k) ; tc = tr(m)%t(i,j,k) ; tm = tr(m)%t(i-1,j,k)
389 dmx = max( tp, tc, tm ) - tc
390 dmn= tc - min( tp, tc, tm )
391 slope_x(i,m) = g%mask2dCu(i,j)*g%mask2dCu(i-1,j) * &
392 sign( min(0.5*abs(tp-tm), 2.0*dmx, 2.0*dmn), tp-tm )
401 if (uhr(i,j,k) == 0.0)
then 404 elseif (uhr(i,j,k) < 0.0)
then 405 hup = hprev(i+1,j,k) - g%areaT(i+1,j)*min_h
406 hlos = max(0.0,uhr(i+1,j,k))
407 if ((((hup - hlos) + uhr(i,j,k)) < 0.0) .and. &
408 ((0.5*hup + uhr(i,j,k)) < 0.0))
then 409 uhh(i) = min(-0.5*hup,-hup+hlos,0.0)
410 domore_u(j,k) = .true.
415 cfl(i) = - uhh(i)/(hprev(i+1,j,k)+h_neglect)
417 hup = hprev(i,j,k) - g%areaT(i,j)*min_h
418 hlos = max(0.0,-uhr(i-1,j,k))
419 if ((((hup - hlos) - uhr(i,j,k)) < 0.0) .and. &
420 ((0.5*hup - uhr(i,j,k)) < 0.0))
then 421 uhh(i) = max(0.5*hup,hup-hlos,0.0)
422 domore_u(j,k) = .true.
427 cfl(i) = uhh(i)/(hprev(i,j,k)+h_neglect)
433 do m=1,ntr ;
do i=is-1,ie
435 if (uhh(i) >= 0.0)
then 442 tp = tr(m)%t(i_up+1,j,k) ; tc = tr(m)%t(i_up,j,k) ; tm = tr(m)%t(i_up-1,j,k)
445 al = ( 5.*tc + ( 2.*tm - tp ) )/6.
446 al = max( min(tc,tm), al) ; al = min( max(tc,tm), al)
447 ar = ( 5.*tc + ( 2.*tp - tm ) )/6.
448 ar = max( min(tc,tp), ar) ; ar = min( max(tc,tp), ar)
450 al = 0.5 * ((tm + tc) + (slope_x(i_up-1,m) - slope_x(i_up,m)) / 3.)
451 ar = 0.5 * ((tc + tp) + (slope_x(i_up,m) - slope_x(i_up+1,m)) / 3.)
454 da = ar - al ; ma = 0.5*( ar + al )
455 if (g%mask2dCu(i_up,j)*g%mask2dCu(i_up-1,j)*(tp-tc)*(tc-tm) <= 0.)
then 457 elseif ( da*(tc-ma) > (da*da)/6. )
then 459 elseif ( da*(tc-ma) < - (da*da)/6. )
then 463 a6 = 6.*tc - 3. * (ar + al)
465 if (uhh(i) >= 0.0)
then 466 flux_x(i,m) = uhh(i)*( ar - 0.5 * cfl(i) * ( &
467 ( ar - al ) - a6 * ( 1. - 2./3. * cfl(i) ) ) )
469 flux_x(i,m) = uhh(i)*( al + 0.5 * cfl(i) * ( &
470 ( ar - al ) + a6 * ( 1. - 2./3. * cfl(i) ) ) )
474 do m=1,ntr ;
do i=is-1,ie
475 if (uhh(i) >= 0.0)
then 485 flux_x(i,m) = uhh(i)*( tc + 0.5 * slope_x(i,m) * ( 1. - cfl(i) ) )
497 tc = tr(m)%t(i+1,j,k)
498 flux_x(i,m) = uhh(i)*( tc - 0.5 * slope_x(i+1,m) * ( 1. - cfl(i) ) )
506 if (
associated(obc))
then ;
if (obc%OBC_pe)
then ;
if (obc%specified_u_BCs_exist_globally)
then 507 do n=1,obc%number_of_segments
508 if (obc%segment(n)%is_E_or_W)
then 509 if (j >= obc%segment(n)%HI%jsd .and. j<= obc%segment(n)%HI%jed)
then 510 i = obc%segment(n)%HI%IsdB
512 if ((uhr(i,j,k) > 0.0) .and. (g%mask2dT(i,j) < 0.5) .or. &
513 (uhr(i,j,k) < 0.0) .and. (g%mask2dT(i+1,j) < 0.5))
then 516 if (
associated(tr(m)%OBC_in_u))
then 517 flux_x(i,m) = uhh(i)*tr(m)%OBC_in_u(i,j,k)
518 else ; flux_x(i,m) = uhh(i)*tr(m)%OBC_inflow_conc ;
endif 524 endif ;
endif ;
endif 529 uhr(i,j,k) = uhr(i,j,k) - uhh(i)
530 if (abs(uhr(i,j,k)) < uh_neglect(i,j)) uhr(i,j,k) = 0.0
533 if ((uhh(i) /= 0.0) .or. (uhh(i-1) /= 0.0))
then 535 hlst(i) = hprev(i,j,k)
536 hprev(i,j,k) = hprev(i,j,k) - (uhh(i) - uhh(i-1))
537 if (hprev(i,j,k) <= 0.0)
then ; do_i(i) = .false.
538 elseif (hprev(i,j,k) < h_neglect*g%areaT(i,j))
then 539 hlst(i) = hlst(i) + (h_neglect*g%areaT(i,j) - hprev(i,j,k))
540 ihnew(i) = 1.0 / (h_neglect*g%areaT(i,j))
541 else ; ihnew(i) = 1.0 / hprev(i,j,k) ;
endif 551 do i=is,ie ;
if ((do_i(i)) .and. (ihnew(i) > 0.0))
then 552 tr(m)%t(i,j,k) = (tr(m)%t(i,j,k) * hlst(i) - &
553 (flux_x(i,m) - flux_x(i-1,m))) * ihnew(i)
557 if (
associated(tr(m)%ad_x))
then ;
do i=is,ie ;
if (do_i(i))
then 558 tr(m)%ad_x(i,j,k) = tr(m)%ad_x(i,j,k) + flux_x(i,m)*idt
559 endif ;
enddo ;
endif 560 if (
associated(tr(m)%ad2d_x))
then ;
do i=is,ie ;
if (do_i(i))
then 561 tr(m)%ad2d_x(i,j) = tr(m)%ad2d_x(i,j) + flux_x(i,m)*idt
562 endif ;
enddo ;
endif 566 if (
associated(tr(m)%advection_xy))
then 567 do i=is,ie ;
if (do_i(i))
then 568 tr(m)%advection_xy(i,j,k) = tr(m)%advection_xy(i,j,k) - (flux_x(i,m) - flux_x(i-1,m)) * idt * g%IareaT(i,j)
580 subroutine advect_y(Tr, hprev, vhr, vh_neglect, OBC, domore_v, ntr, Idt, &
581 is, ie, js, je, k, G, GV, usePPM, useHuynh)
584 type(
tracer_type),
dimension(ntr),
intent(inout) :: Tr
585 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: hprev
586 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhr
587 real,
dimension(SZI_(G),SZJB_(G)),
intent(inout) :: vh_neglect
589 logical,
dimension(SZJB_(G),SZK_(G)),
intent(inout) :: domore_v
590 real,
intent(in) :: Idt
591 integer,
intent(in) :: ntr, is, ie, js, je,k
592 logical,
intent(in) :: usePPM, useHuynh
594 real,
dimension(SZI_(G),ntr,SZJ_(G)) :: &
597 real,
dimension(SZI_(G),ntr,SZJB_(G)) :: &
601 real :: vhh(szi_(g),szjb_(g))
607 real,
dimension(SZIB_(G)) :: &
614 logical :: do_j_tr(szj_(g))
615 logical :: do_i(szib_(g))
617 integer :: i, j, j2, m, n, j_up, stencil
618 real :: aR, aL, dMx, dMn, Tp, Tc, Tm, dA, mA, a6
619 logical :: usePLMslope
621 useplmslope = .not. (useppm .and. usehuynh)
624 if (useppm .and. .not. usehuynh) stencil = 2
626 min_h = 0.1*gv%Angstrom
627 h_neglect = gv%H_subroundoff
642 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 646 if (useplmslope)
then 647 do j=js-stencil,je+stencil ;
if (do_j_tr(j))
then ;
do m=1,ntr ;
do i=is,ie
662 tp = tr(m)%t(i,j+1,k) ; tc = tr(m)%t(i,j,k) ; tm = tr(m)%t(i,j-1,k)
663 dmx = max( tp, tc, tm ) - tc
664 dmn= tc - min( tp, tc, tm )
665 slope_y(i,m,j) = g%mask2dCv(i,j)*g%mask2dCv(i,j-1) * &
666 sign( min(0.5*abs(tp-tm), 2.0*dmx, 2.0*dmn), tp-tm )
667 enddo ;
enddo ;
endif ;
enddo 674 do j=js-1,je ;
if (domore_v(j,k))
then 675 domore_v(j,k) = .false.
678 if (vhr(i,j,k) == 0.0)
then 681 elseif (vhr(i,j,k) < 0.0)
then 682 hup = hprev(i,j+1,k) - g%areaT(i,j+1)*min_h
683 hlos = max(0.0,vhr(i,j+1,k))
684 if ((((hup - hlos) + vhr(i,j,k)) < 0.0) .and. &
685 ((0.5*hup + vhr(i,j,k)) < 0.0))
then 686 vhh(i,j) = min(-0.5*hup,-hup+hlos,0.0)
687 domore_v(j,k) = .true.
689 vhh(i,j) = vhr(i,j,k)
692 cfl(i) = - vhh(i,j) / (hprev(i,j+1,k)+h_neglect)
694 hup = hprev(i,j,k) - g%areaT(i,j)*min_h
695 hlos = max(0.0,-vhr(i,j-1,k))
696 if ((((hup - hlos) - vhr(i,j,k)) < 0.0) .and. &
697 ((0.5*hup - vhr(i,j,k)) < 0.0))
then 698 vhh(i,j) = max(0.5*hup,hup-hlos,0.0)
699 domore_v(j,k) = .true.
701 vhh(i,j) = vhr(i,j,k)
704 cfl(i) = vhh(i,j) / (hprev(i,j,k)+h_neglect)
709 do m=1,ntr ;
do i=is,ie
711 if (vhh(i,j) >= 0.0)
then 718 tp = tr(m)%t(i,j_up+1,k) ; tc = tr(m)%t(i,j_up,k) ; tm = tr(m)%t(i,j_up-1,k)
721 al = ( 5.*tc + ( 2.*tm - tp ) )/6.
722 al = max( min(tc,tm), al) ; al = min( max(tc,tm), al)
723 ar = ( 5.*tc + ( 2.*tp - tm ) )/6.
724 ar = max( min(tc,tp), ar) ; ar = min( max(tc,tp), ar)
726 al = 0.5 * ((tm + tc) + (slope_y(i,m,j_up-1) - slope_y(i,m,j_up)) / 3.)
727 ar = 0.5 * ((tc + tp) + (slope_y(i,m,j_up) - slope_y(i,m,j_up+1)) / 3.)
730 da = ar - al ; ma = 0.5*( ar + al )
731 if (g%mask2dCv(i,j_up)*g%mask2dCv(i,j_up-1)*(tp-tc)*(tc-tm) <= 0.)
then 733 elseif ( da*(tc-ma) > (da*da)/6. )
then 735 elseif ( da*(tc-ma) < - (da*da)/6. )
then 739 a6 = 6.*tc - 3. * (ar + al)
741 if (vhh(i,j) >= 0.0)
then 742 flux_y(i,m,j) = vhh(i,j)*( ar - 0.5 * cfl(i) * ( &
743 ( ar - al ) - a6 * ( 1. - 2./3. * cfl(i) ) ) )
745 flux_y(i,m,j) = vhh(i,j)*( al + 0.5 * cfl(i) * ( &
746 ( ar - al ) + a6 * ( 1. - 2./3. * cfl(i) ) ) )
750 do m=1,ntr ;
do i=is,ie
751 if (vhh(i,j) >= 0.0)
then 761 flux_y(i,m,j) = vhh(i,j)*( tc + 0.5 * slope_y(i,m,j) * ( 1. - cfl(i) ) )
773 tc = tr(m)%t(i,j+1,k)
774 flux_y(i,m,j) = vhh(i,j)*( tc - 0.5 * slope_y(i,m,j+1) * ( 1. - cfl(i) ) )
781 if (
associated(obc))
then ;
if (obc%OBC_pe)
then ;
if (obc%specified_v_BCs_exist_globally)
then 782 do n=1,obc%number_of_segments
783 if (obc%segment(n)%is_N_or_S)
then 784 if (j >= obc%segment(n)%HI%JsdB .and. j<= obc%segment(n)%HI%JedB)
then 785 i = obc%segment(n)%HI%isd
787 if ((vhr(i,j,k) > 0.0) .and. (g%mask2dT(i,j) < 0.5) .or. &
788 (vhr(i,j,k) < 0.0) .and. (g%mask2dT(i,j+1) < 0.5))
then 789 vhh(i,j) = vhr(i,j,k)
791 if (
associated(tr(m)%OBC_in_v))
then 792 flux_y(i,m,j) = vhh(i,j)*tr(m)%OBC_in_v(i,j,k)
793 else ; flux_y(i,m,j) = vhh(i,j)*tr(m)%OBC_inflow_conc ;
endif 799 endif ;
endif ;
endif 801 do i=is,ie ; vhh(i,j) = 0.0 ;
enddo 802 do m=1,ntr ;
do i=is,ie ; flux_y(i,m,j) = 0.0 ;
enddo ;
enddo 805 do j=js-1,je ;
do i=is,ie
806 vhr(i,j,k) = vhr(i,j,k) - vhh(i,j)
807 if (abs(vhr(i,j,k)) < vh_neglect(i,j)) vhr(i,j,k) = 0.0
812 do j=js,je ;
if (do_j_tr(j))
then 814 if ((vhh(i,j) /= 0.0) .or. (vhh(i,j-1) /= 0.0))
then 816 hlst(i) = hprev(i,j,k)
817 hprev(i,j,k) = max(hprev(i,j,k) - (vhh(i,j) - vhh(i,j-1)), 0.0)
818 if (hprev(i,j,k) <= 0.0)
then ; do_i(i) = .false.
819 elseif (hprev(i,j,k) < h_neglect*g%areaT(i,j))
then 820 hlst(i) = hlst(i) + (h_neglect*g%areaT(i,j) - hprev(i,j,k))
821 ihnew(i) = 1.0 / (h_neglect*g%areaT(i,j))
822 else ; ihnew(i) = 1.0 / hprev(i,j,k) ;
endif 823 else ; do_i(i) = .false. ;
endif 828 do i=is,ie ;
if (do_i(i))
then 829 tr(m)%t(i,j,k) = (tr(m)%t(i,j,k) * hlst(i) - &
830 (flux_y(i,m,j) - flux_y(i,m,j-1))) * ihnew(i)
834 if (
associated(tr(m)%ad_y))
then ;
do i=is,ie ;
if (do_i(i))
then 835 tr(m)%ad_y(i,j,k) = tr(m)%ad_y(i,j,k) + flux_y(i,m,j)*idt
836 endif ;
enddo ;
endif 837 if (
associated(tr(m)%ad2d_y))
then ;
do i=is,ie ;
if (do_i(i))
then 838 tr(m)%ad2d_y(i,j) = tr(m)%ad2d_y(i,j) + flux_y(i,m,j)*idt
839 endif ;
enddo ;
endif 843 if (
associated(tr(m)%advection_xy))
then 844 do i=is,ie ;
if (do_i(i))
then 845 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 * g%IareaT(i,j)
858 type(time_type),
target,
intent(in) :: Time
861 type(
diag_ctrl),
target,
intent(inout) :: diag
864 integer,
save :: init_calls = 0
867 #include "version_variable.h" 868 character(len=40) :: mdl =
"MOM_tracer_advect" 869 character(len=256) :: mesg
871 if (
associated(cs))
then 872 call mom_error(warning,
"tracer_advect_init called with associated control structure.")
881 call get_param(param_file, mdl,
"DT", cs%dt, fail_if_missing=.true., &
882 desc=
"The (baroclinic) dynamics time step.", units=
"s")
883 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false.)
884 call get_param(param_file, mdl,
"TRACER_ADVECTION_SCHEME", mesg, &
885 desc=
"The horizontal transport scheme for tracers:\n"//&
886 " PLM - Piecewise Linear Method\n"//&
887 " PPM:H3 - Piecewise Parabolic Method (Huyhn 3rd order)\n"// &
888 " PPM - Piecewise Parabolic Method (Colella-Woodward)" &
890 select case (trim(mesg))
898 cs%useHuynh = .false.
900 call mom_error(fatal,
"MOM_tracer_advect, tracer_advect_init: "//&
901 "Unknown TRACER_ADVECTION_SCHEME = "//trim(mesg))
904 id_clock_advect = cpu_clock_id(
'(Ocean advect tracer)', grain=clock_module)
905 id_clock_pass = cpu_clock_id(
'(Ocean tracer halo updates)', grain=clock_routine)
906 id_clock_sync = cpu_clock_id(
'(Ocean tracer global synch)', grain=clock_routine)
914 if (
associated(cs))
deallocate(cs)
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.
Control structure for this module.
Ocean grid type. See mom_grid for details.
Provides the ocean grid type.
subroutine, public do_group_pass(group, MOM_dom)
subroutine, public advect_tracer(h_end, uhtr, vhtr, OBC, dt, G, GV, CS, Reg, h_prev_opt, max_iter_in, x_first_in, uhr_out, vhr_out, h_out)
This routine time steps the tracer concentration using a monotonic, conservative, weakly diffusive sc...
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
subroutine, public tracer_advect_init(Time, G, param_file, diag, CS)
Initialize lateral tracer advection module.
Type to carry basic tracer information.
logical function, public is_root_pe()
subroutine, public tracer_advect_end(CS)
Close the tracer advection module.
subroutine, public mom_mesg(message, verb, all_print)
integer, parameter, public obc_direction_e
Indicates the boundary is an effective eastern boundary.
This program contains the subroutines that advect tracers along coordinate surfaces.
subroutine advect_x(Tr, hprev, uhr, uh_neglect, OBC, domore_u, ntr, Idt, is, ie, js, je, k, G, GV, usePPM, useHuynh)
This subroutine does 1-d flux-form advection in the zonal direction using a monotonic piecewise linea...
integer, parameter, public obc_none
subroutine advect_y(Tr, hprev, vhr, vh_neglect, OBC, domore_v, ntr, Idt, is, ie, js, je, k, G, GV, usePPM, useHuynh)
This subroutine does 1-d flux-form advection using a monotonic piecewise linear scheme.
Controls where open boundary conditions are applied.
subroutine, public mom_error(level, message, all_print)