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
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, 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
64 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
65 optional,
intent(in) :: h_prev_opt
66 integer,
optional,
intent(in) :: max_iter_in
67 logical,
optional,
intent(in) :: x_first_in
69 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
70 optional,
intent(out) :: uhr_out
72 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
73 optional,
intent(out) :: vhr_out
75 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
76 optional,
intent(out) :: h_out
79 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
81 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)) :: &
83 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)) :: &
85 real :: uh_neglect(szib_(g),szj_(g))
86 real :: vh_neglect(szi_(g),szjb_(g))
91 logical :: domore_u(szj_(g),szk_(g))
92 logical :: domore_v(szjb_(g),szk_(g))
96 integer :: domore_k(szk_(g))
99 integer :: i, j, k, m, is, ie, js, je, isd, ied, jsd, jed, nz, itt, ntr, do_any
100 integer :: isv, iev, jsv, jev
101 integer :: isdb, iedb, jsdb, jedb
103 domore_u(:,:) = .false.
104 domore_v(:,:) = .false.
105 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
106 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
107 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
108 landvolfill = 1.0e-20
111 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_tracer_advect: "// &
112 "tracer_advect_init must be called before advect_tracer.")
113 if (.not.
associated(reg))
call mom_error(fatal,
"MOM_tracer_advect: "// &
114 "register_tracer must be called before advect_tracer.")
115 if (reg%ntr==0)
return
116 call cpu_clock_begin(id_clock_advect)
117 x_first = (mod(g%first_direction,2) == 0)
120 if (cs%usePPM .and. .not. cs%useHuynh) stencil = 3
123 do m=1,ntr ; tr(m) = reg%Tr(m) ;
enddo
126 max_iter = 2*int(ceiling(dt/cs%dt)) + 1
128 if (
present(max_iter_in)) max_iter = max_iter_in
129 if (
present(x_first_in)) x_first = x_first_in
130 call cpu_clock_begin(id_clock_pass)
136 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
226 do k=1,nz ;
if (domore_k(k) > 0)
then
227 do j=jsv,jev ;
if (.not.domore_u(j,k))
then
228 do i=isv+stencil-1,iev-stencil;
if (uhr(i,j,k) /= 0.0)
then
229 domore_u(j,k) = .true. ;
exit
232 do j=jsv+stencil-1,jev-stencil ;
if (.not.domore_v(j,k))
then
233 do i=isv+stencil,iev-stencil;
if (vhr(i,j,k) /= 0.0)
then
234 domore_v(j,k) = .true. ;
exit
241 do j=jsv,jev ;
if (domore_u(j,k)) domore_k(k) = 1 ;
enddo
242 do j=jsv+stencil-1,jev-stencil ;
if (domore_v(j,k)) domore_k(k) = 1 ;
enddo
249 isv = isv + stencil ; iev = iev - stencil
250 jsv = jsv + stencil ; jev = jev - stencil
261 do k=1,nz ;
if (domore_k(k) > 0)
then
266 call advect_x(tr, hprev, uhr, uh_neglect, obc, domore_u, ntr, idt, &
267 isv, iev, jsv-stencil, jev+stencil, k, g, gv, cs%usePPM, cs%useHuynh)
270 call advect_y(tr, hprev, vhr, vh_neglect, obc, domore_v, ntr, idt, &
271 isv, iev, jsv, jev, k, g, gv, cs%usePPM, cs%useHuynh)
274 do j=jsv-stencil,jev+stencil ;
if (domore_u(j,k)) domore_k(k) = 1 ;
enddo
275 do j=jsv-1,jev ;
if (domore_v(j,k)) domore_k(k) = 1 ;
enddo
280 call advect_y(tr, hprev, vhr, vh_neglect, obc, domore_v, ntr, idt, &
281 isv-stencil, iev+stencil, jsv, jev, k, g, gv, cs%usePPM, cs%useHuynh)
284 call advect_x(tr, hprev, uhr, uh_neglect, obc, domore_u, ntr, idt, &
285 isv, iev, jsv, jev, k, g, gv, cs%usePPM, cs%useHuynh)
288 do j=jsv,jev ;
if (domore_u(j,k)) domore_k(k) = 1 ;
enddo
289 do j=jsv-1,jev ;
if (domore_v(j,k)) domore_k(k) = 1 ;
enddo
297 if (itt >= max_iter)
then
302 if (isv > is-stencil)
then
304 call cpu_clock_begin(id_clock_sync)
305 call sum_across_pes(domore_k(:), nz)
306 call cpu_clock_end(id_clock_sync)
307 do k=1,nz ; do_any = do_any + domore_k(k) ;
enddo
308 if (do_any == 0)
then
316 if (
present(uhr_out)) uhr_out(:,:,:) = uhr(:,:,:)
317 if (
present(vhr_out)) vhr_out(:,:,:) = vhr(:,:,:)
318 if (
present(h_out)) h_out(:,:,:) = hprev(:,:,:)
320 call cpu_clock_end(id_clock_advect)
322 end subroutine advect_tracer
327 subroutine advect_x(Tr, hprev, uhr, uh_neglect, OBC, domore_u, ntr, Idt, &
328 is, ie, js, je, k, G, GV, usePPM, useHuynh)
331 type(
tracer_type),
dimension(ntr),
intent(inout) :: Tr
332 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: hprev
334 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhr
336 real,
dimension(SZIB_(G),SZJ_(G)),
intent(inout) :: uh_neglect
339 logical,
dimension(SZJ_(G),SZK_(G)),
intent(inout) :: domore_u
341 real,
intent(in) :: Idt
342 integer,
intent(in) :: ntr
343 integer,
intent(in) :: is
344 integer,
intent(in) :: ie
345 integer,
intent(in) :: js
346 integer,
intent(in) :: je
347 integer,
intent(in) :: k
348 logical,
intent(in) :: usePPM
349 logical,
intent(in) :: useHuynh
352 real,
dimension(SZI_(G),ntr) :: &
354 real,
dimension(SZIB_(G),ntr) :: &
362 real :: uhh(SZIB_(G))
364 real,
dimension(SZIB_(G)) :: &
372 logical :: do_i(SZIB_(G))
374 integer :: i, j, m, n, i_up, stencil
375 real :: aR, aL, dMx, dMn, Tp, Tc, Tm, dA, mA, a6
376 real :: fac1,u_L_in,u_L_out
378 integer :: ishift, idir
380 logical :: usePLMslope
382 useplmslope = .not. (useppm .and. usehuynh)
385 if (useppm .and. .not. usehuynh) stencil = 2
387 min_h = 0.1*gv%Angstrom_H
388 h_neglect = gv%H_subroundoff
392 do i=is-1,ie ; cfl(i) = 0.0 ;
enddo
394 do j=js,je ;
if (domore_u(j,k))
then
395 domore_u(j,k) = .false.
399 if (useplmslope)
then
400 do m=1,ntr ;
do i=is-stencil,ie+stencil
415 tp = tr(m)%t(i+1,j,k) ; tc = tr(m)%t(i,j,k) ; tm = tr(m)%t(i-1,j,k)
416 dmx = max( tp, tc, tm ) - tc
417 dmn= tc - min( tp, tc, tm )
418 slope_x(i,m) = g%mask2dCu(i,j)*g%mask2dCu(i-1,j) * &
419 sign( min(0.5*abs(tp-tm), 2.0*dmx, 2.0*dmn), tp-tm )
428 if (uhr(i,j,k) == 0.0)
then
431 elseif (uhr(i,j,k) < 0.0)
then
432 hup = hprev(i+1,j,k) - g%areaT(i+1,j)*min_h
433 hlos = max(0.0,uhr(i+1,j,k))
434 if ((((hup - hlos) + uhr(i,j,k)) < 0.0) .and. &
435 ((0.5*hup + uhr(i,j,k)) < 0.0))
then
436 uhh(i) = min(-0.5*hup,-hup+hlos,0.0)
437 domore_u(j,k) = .true.
442 cfl(i) = - uhh(i)/(hprev(i+1,j,k)+h_neglect)
444 hup = hprev(i,j,k) - g%areaT(i,j)*min_h
445 hlos = max(0.0,-uhr(i-1,j,k))
446 if ((((hup - hlos) - uhr(i,j,k)) < 0.0) .and. &
447 ((0.5*hup - uhr(i,j,k)) < 0.0))
then
448 uhh(i) = max(0.5*hup,hup-hlos,0.0)
449 domore_u(j,k) = .true.
454 cfl(i) = uhh(i)/(hprev(i,j,k)+h_neglect)
460 do m=1,ntr ;
do i=is-1,ie
462 if (uhh(i) >= 0.0)
then
469 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)
472 al = ( 5.*tc + ( 2.*tm - tp ) )/6.
473 al = max( min(tc,tm), al) ; al = min( max(tc,tm), al)
474 ar = ( 5.*tc + ( 2.*tp - tm ) )/6.
475 ar = max( min(tc,tp), ar) ; ar = min( max(tc,tp), ar)
477 al = 0.5 * ((tm + tc) + (slope_x(i_up-1,m) - slope_x(i_up,m)) / 3.)
478 ar = 0.5 * ((tc + tp) + (slope_x(i_up,m) - slope_x(i_up+1,m)) / 3.)
481 da = ar - al ; ma = 0.5*( ar + al )
482 if (g%mask2dCu(i_up,j)*g%mask2dCu(i_up-1,j)*(tp-tc)*(tc-tm) <= 0.)
then
484 elseif ( da*(tc-ma) > (da*da)/6. )
then
486 elseif ( da*(tc-ma) < - (da*da)/6. )
then
490 a6 = 6.*tc - 3. * (ar + al)
492 if (uhh(i) >= 0.0)
then
493 flux_x(i,m) = uhh(i)*( ar - 0.5 * cfl(i) * ( &
494 ( ar - al ) - a6 * ( 1. - 2./3. * cfl(i) ) ) )
496 flux_x(i,m) = uhh(i)*( al + 0.5 * cfl(i) * ( &
497 ( ar - al ) + a6 * ( 1. - 2./3. * cfl(i) ) ) )
501 do m=1,ntr ;
do i=is-1,ie
502 if (uhh(i) >= 0.0)
then
512 flux_x(i,m) = uhh(i)*( tc + 0.5 * slope_x(i,m) * ( 1. - cfl(i) ) )
524 tc = tr(m)%t(i+1,j,k)
525 flux_x(i,m) = uhh(i)*( tc - 0.5 * slope_x(i+1,m) * ( 1. - cfl(i) ) )
533 if (
associated(obc))
then ;
if (obc%OBC_pe)
then
534 if (obc%specified_u_BCs_exist_globally)
then
535 do n=1,obc%number_of_segments
536 segment=>obc%segment(n)
537 if (.not. segment%specified) cycle
538 if (.not.
associated(segment%tr_Reg)) cycle
539 if (segment%is_E_or_W)
then
540 if (j>=segment%HI%jsd .and. j<=segment%HI%jed)
then
544 if ((uhr(i,j,k) > 0.0) .and. (segment%direction == obc_direction_w) .or. &
545 (uhr(i,j,k) < 0.0) .and. (segment%direction == obc_direction_e))
then
549 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
550 flux_x(i,m) = uhh(i)*segment%tr_Reg%Tr(m)%tres(i,j,k)
551 else ; flux_x(i,m) = uhh(i)*segment%tr_Reg%Tr(m)%OBC_inflow_conc ;
endif
559 if (obc%open_u_BCs_exist_globally)
then
560 do n=1,obc%number_of_segments
561 segment=>obc%segment(n)
563 if (segment%is_E_or_W .and. (j >= segment%HI%jsd .and. j<= segment%HI%jed))
then
564 if (segment%specified) cycle
565 if (.not.
associated(segment%tr_Reg)) cycle
568 if (segment%direction == obc_direction_w)
then
575 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
577 u_l_in=max(idir*uhh(i)*segment%Tr_InvLscale3_in,0.)
578 u_l_out=min(idir*uhh(i)*segment%Tr_InvLscale3_out,0.)
579 fac1=1.0+dt*(u_l_in-u_l_out)
580 segment%tr_Reg%Tr(m)%tres(i,j,k)= (1.0/fac1)*(segment%tr_Reg%Tr(m)%tres(i,j,k) + &
581 dt*(u_l_in*tr(m)%t(i+ishift,j,k) - &
582 u_l_out*segment%tr_Reg%Tr(m)%t(i,j,k)))
587 if ((uhr(i,j,k) > 0.0) .and. (g%mask2dT(i,j) < 0.5) .or. &
588 (uhr(i,j,k) < 0.0) .and. (g%mask2dT(i+1,j) < 0.5))
then
591 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
592 flux_x(i,m) = uhh(i)*segment%tr_Reg%Tr(m)%tres(i,j,k)
593 else; flux_x(i,m) = uhh(i)*segment%tr_Reg%Tr(m)%OBC_inflow_conc;
endif
604 uhr(i,j,k) = uhr(i,j,k) - uhh(i)
605 if (abs(uhr(i,j,k)) < uh_neglect(i,j)) uhr(i,j,k) = 0.0
608 if ((uhh(i) /= 0.0) .or. (uhh(i-1) /= 0.0))
then
610 hlst(i) = hprev(i,j,k)
611 hprev(i,j,k) = hprev(i,j,k) - (uhh(i) - uhh(i-1))
612 if (hprev(i,j,k) <= 0.0)
then ; do_i(i) = .false.
613 elseif (hprev(i,j,k) < h_neglect*g%areaT(i,j))
then
614 hlst(i) = hlst(i) + (h_neglect*g%areaT(i,j) - hprev(i,j,k))
615 ihnew(i) = 1.0 / (h_neglect*g%areaT(i,j))
616 else ; ihnew(i) = 1.0 / hprev(i,j,k) ;
endif
626 do i=is,ie ;
if ((do_i(i)) .and. (ihnew(i) > 0.0))
then
627 tr(m)%t(i,j,k) = (tr(m)%t(i,j,k) * hlst(i) - &
628 (flux_x(i,m) - flux_x(i-1,m))) * ihnew(i)
632 if (
associated(tr(m)%ad_x))
then ;
do i=is,ie ;
if (do_i(i))
then
633 tr(m)%ad_x(i,j,k) = tr(m)%ad_x(i,j,k) + flux_x(i,m)*idt
634 endif ;
enddo ;
endif
635 if (
associated(tr(m)%ad2d_x))
then ;
do i=is,ie ;
if (do_i(i))
then
636 tr(m)%ad2d_x(i,j) = tr(m)%ad2d_x(i,j) + flux_x(i,m)*idt
637 endif ;
enddo ;
endif
641 if (
associated(tr(m)%advection_xy))
then
642 do i=is,ie ;
if (do_i(i))
then
643 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)
651 end subroutine advect_x
655 subroutine advect_y(Tr, hprev, vhr, vh_neglect, OBC, domore_v, ntr, Idt, &
656 is, ie, js, je, k, G, GV, usePPM, useHuynh)
659 type(
tracer_type),
dimension(ntr),
intent(inout) :: Tr
660 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: hprev
662 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhr
664 real,
dimension(SZI_(G),SZJB_(G)),
intent(inout) :: vh_neglect
667 logical,
dimension(SZJB_(G),SZK_(G)),
intent(inout) :: domore_v
669 real,
intent(in) :: Idt
670 integer,
intent(in) :: ntr
671 integer,
intent(in) :: is
672 integer,
intent(in) :: ie
673 integer,
intent(in) :: js
674 integer,
intent(in) :: je
675 integer,
intent(in) :: k
676 logical,
intent(in) :: usePPM
677 logical,
intent(in) :: useHuynh
680 real,
dimension(SZI_(G),ntr,SZJ_(G)) :: &
682 real,
dimension(SZI_(G),ntr,SZJB_(G)) :: &
686 real :: vhh(SZI_(G),SZJB_(G))
692 real,
dimension(SZIB_(G)) :: &
700 logical :: do_j_tr(SZJ_(G))
701 logical :: do_i(SZIB_(G))
703 integer :: i, j, j2, m, n, j_up, stencil
704 real :: aR, aL, dMx, dMn, Tp, Tc, Tm, dA, mA, a6
705 real :: fac1,v_L_in,v_L_out
706 integer :: jshift, jdir
709 logical :: usePLMslope
711 useplmslope = .not. (useppm .and. usehuynh)
714 if (useppm .and. .not. usehuynh) stencil = 2
716 min_h = 0.1*gv%Angstrom_H
717 h_neglect = gv%H_subroundoff
732 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
736 if (useplmslope)
then
737 do j=js-stencil,je+stencil ;
if (do_j_tr(j))
then ;
do m=1,ntr ;
do i=is,ie
752 tp = tr(m)%t(i,j+1,k) ; tc = tr(m)%t(i,j,k) ; tm = tr(m)%t(i,j-1,k)
753 dmx = max( tp, tc, tm ) - tc
754 dmn= tc - min( tp, tc, tm )
755 slope_y(i,m,j) = g%mask2dCv(i,j)*g%mask2dCv(i,j-1) * &
756 sign( min(0.5*abs(tp-tm), 2.0*dmx, 2.0*dmn), tp-tm )
757 enddo ;
enddo ;
endif ;
enddo
764 do j=js-1,je ;
if (domore_v(j,k))
then
765 domore_v(j,k) = .false.
768 if (vhr(i,j,k) == 0.0)
then
771 elseif (vhr(i,j,k) < 0.0)
then
772 hup = hprev(i,j+1,k) - g%areaT(i,j+1)*min_h
773 hlos = max(0.0,vhr(i,j+1,k))
774 if ((((hup - hlos) + vhr(i,j,k)) < 0.0) .and. &
775 ((0.5*hup + vhr(i,j,k)) < 0.0))
then
776 vhh(i,j) = min(-0.5*hup,-hup+hlos,0.0)
777 domore_v(j,k) = .true.
779 vhh(i,j) = vhr(i,j,k)
782 cfl(i) = - vhh(i,j) / (hprev(i,j+1,k)+h_neglect)
784 hup = hprev(i,j,k) - g%areaT(i,j)*min_h
785 hlos = max(0.0,-vhr(i,j-1,k))
786 if ((((hup - hlos) - vhr(i,j,k)) < 0.0) .and. &
787 ((0.5*hup - vhr(i,j,k)) < 0.0))
then
788 vhh(i,j) = max(0.5*hup,hup-hlos,0.0)
789 domore_v(j,k) = .true.
791 vhh(i,j) = vhr(i,j,k)
794 cfl(i) = vhh(i,j) / (hprev(i,j,k)+h_neglect)
799 do m=1,ntr ;
do i=is,ie
801 if (vhh(i,j) >= 0.0)
then
808 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)
811 al = ( 5.*tc + ( 2.*tm - tp ) )/6.
812 al = max( min(tc,tm), al) ; al = min( max(tc,tm), al)
813 ar = ( 5.*tc + ( 2.*tp - tm ) )/6.
814 ar = max( min(tc,tp), ar) ; ar = min( max(tc,tp), ar)
816 al = 0.5 * ((tm + tc) + (slope_y(i,m,j_up-1) - slope_y(i,m,j_up)) / 3.)
817 ar = 0.5 * ((tc + tp) + (slope_y(i,m,j_up) - slope_y(i,m,j_up+1)) / 3.)
820 da = ar - al ; ma = 0.5*( ar + al )
821 if (g%mask2dCv(i,j_up)*g%mask2dCv(i,j_up-1)*(tp-tc)*(tc-tm) <= 0.)
then
823 elseif ( da*(tc-ma) > (da*da)/6. )
then
825 elseif ( da*(tc-ma) < - (da*da)/6. )
then
829 a6 = 6.*tc - 3. * (ar + al)
831 if (vhh(i,j) >= 0.0)
then
832 flux_y(i,m,j) = vhh(i,j)*( ar - 0.5 * cfl(i) * ( &
833 ( ar - al ) - a6 * ( 1. - 2./3. * cfl(i) ) ) )
835 flux_y(i,m,j) = vhh(i,j)*( al + 0.5 * cfl(i) * ( &
836 ( ar - al ) + a6 * ( 1. - 2./3. * cfl(i) ) ) )
840 do m=1,ntr ;
do i=is,ie
841 if (vhh(i,j) >= 0.0)
then
851 flux_y(i,m,j) = vhh(i,j)*( tc + 0.5 * slope_y(i,m,j) * ( 1. - cfl(i) ) )
863 tc = tr(m)%t(i,j+1,k)
864 flux_y(i,m,j) = vhh(i,j)*( tc - 0.5 * slope_y(i,m,j+1) * ( 1. - cfl(i) ) )
871 if (
associated(obc))
then ;
if (obc%OBC_pe)
then
872 if (obc%specified_v_BCs_exist_globally)
then
873 do n=1,obc%number_of_segments
874 segment=>obc%segment(n)
875 if (.not. segment%specified) cycle
876 if (.not.
associated(segment%tr_Reg)) cycle
877 if (obc%segment(n)%is_N_or_S)
then
878 if (j >= segment%HI%JsdB .and. j<= segment%HI%JedB)
then
879 do i=segment%HI%isd,segment%HI%ied
882 if ((vhr(i,j,k) > 0.0) .and. (segment%direction == obc_direction_s) .or. &
883 (vhr(i,j,k) < 0.0) .and. (segment%direction == obc_direction_n))
then
884 vhh(i,j) = vhr(i,j,k)
886 if (
associated(segment%tr_Reg%Tr(m)%t))
then
887 flux_y(i,m,j) = vhh(i,j)*obc%segment(n)%tr_Reg%Tr(m)%tres(i,j,k)
888 else ; flux_y(i,m,j) = vhh(i,j)*obc%segment(n)%tr_Reg%Tr(m)%OBC_inflow_conc ;
endif
898 if (obc%open_v_BCs_exist_globally)
then
899 do n=1,obc%number_of_segments
900 segment=>obc%segment(n)
901 if (segment%specified) cycle
902 if (.not.
associated(segment%tr_Reg)) cycle
903 if (segment%is_N_or_S .and. &
904 (j >= segment%HI%JsdB .and. j<= segment%HI%JedB))
then
907 if (segment%direction == obc_direction_s)
then
911 do i=segment%HI%isd,segment%HI%ied
915 if (
associated(segment%tr_Reg%Tr(m)%tres))
then
917 v_l_in=max(jdir*vhh(i,j)*segment%Tr_InvLscale3_in,0.)
918 v_l_out=min(jdir*vhh(i,j)*segment%Tr_InvLscale3_out,0.)
919 fac1=1.0+dt*(v_l_in-v_l_out)
920 segment%tr_Reg%Tr(m)%tres(i,j,k)= (1.0/fac1)*(segment%tr_Reg%Tr(m)%tres(i,j,k) + &
921 dt*v_l_in*tr(m)%t(i,j+jshift,k) - &
922 dt*v_l_out*segment%tr_Reg%Tr(m)%t(i,j,k))
926 if ((vhr(i,j,k) > 0.0) .and. (g%mask2dT(i,j) < 0.5) .or. &
927 (vhr(i,j,k) < 0.0) .and. (g%mask2dT(i,j+1) < 0.5))
then
928 vhh(i,j) = vhr(i,j,k)
930 if (
associated(segment%tr_Reg%Tr(m)%t))
then
931 flux_y(i,m,j) = vhh(i,j)*segment%tr_Reg%Tr(m)%tres(i,j,k)
932 else ; flux_y(i,m,j) = vhh(i,j)*segment%tr_Reg%Tr(m)%OBC_inflow_conc ;
endif
942 do i=is,ie ; vhh(i,j) = 0.0 ;
enddo
943 do m=1,ntr ;
do i=is,ie ; flux_y(i,m,j) = 0.0 ;
enddo ;
enddo
946 do j=js-1,je ;
do i=is,ie
947 vhr(i,j,k) = vhr(i,j,k) - vhh(i,j)
948 if (abs(vhr(i,j,k)) < vh_neglect(i,j)) vhr(i,j,k) = 0.0
953 do j=js,je ;
if (do_j_tr(j))
then
955 if ((vhh(i,j) /= 0.0) .or. (vhh(i,j-1) /= 0.0))
then
957 hlst(i) = hprev(i,j,k)
958 hprev(i,j,k) = max(hprev(i,j,k) - (vhh(i,j) - vhh(i,j-1)), 0.0)
959 if (hprev(i,j,k) <= 0.0)
then ; do_i(i) = .false.
960 elseif (hprev(i,j,k) < h_neglect*g%areaT(i,j))
then
961 hlst(i) = hlst(i) + (h_neglect*g%areaT(i,j) - hprev(i,j,k))
962 ihnew(i) = 1.0 / (h_neglect*g%areaT(i,j))
963 else ; ihnew(i) = 1.0 / hprev(i,j,k) ;
endif
964 else ; do_i(i) = .false. ;
endif
969 do i=is,ie ;
if (do_i(i))
then
970 tr(m)%t(i,j,k) = (tr(m)%t(i,j,k) * hlst(i) - &
971 (flux_y(i,m,j) - flux_y(i,m,j-1))) * ihnew(i)
975 if (
associated(tr(m)%ad_y))
then ;
do i=is,ie ;
if (do_i(i))
then
976 tr(m)%ad_y(i,j,k) = tr(m)%ad_y(i,j,k) + flux_y(i,m,j)*idt
977 endif ;
enddo ;
endif
978 if (
associated(tr(m)%ad2d_y))
then ;
do i=is,ie ;
if (do_i(i))
then
979 tr(m)%ad2d_y(i,j) = tr(m)%ad2d_y(i,j) + flux_y(i,m,j)*idt
980 endif ;
enddo ;
endif
984 if (
associated(tr(m)%advection_xy))
then
985 do i=is,ie ;
if (do_i(i))
then
986 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)
995 end subroutine advect_y
998 subroutine tracer_advect_init(Time, G, param_file, diag, CS)
999 type(time_type),
target,
intent(in) :: time
1002 type(
diag_ctrl),
target,
intent(inout) :: diag
1005 integer,
save :: init_calls = 0
1008 #include "version_variable.h"
1009 character(len=40) :: mdl =
"MOM_tracer_advect"
1010 character(len=256) :: mesg
1012 if (
associated(cs))
then
1013 call mom_error(warning,
"tracer_advect_init called with associated control structure.")
1022 call get_param(param_file, mdl,
"DT", cs%dt, fail_if_missing=.true., &
1023 desc=
"The (baroclinic) dynamics time step.", units=
"s")
1024 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false.)
1025 call get_param(param_file, mdl,
"TRACER_ADVECTION_SCHEME", mesg, &
1026 desc=
"The horizontal transport scheme for tracers:\n"//&
1027 " PLM - Piecewise Linear Method\n"//&
1028 " PPM:H3 - Piecewise Parabolic Method (Huyhn 3rd order)\n"// &
1029 " PPM - Piecewise Parabolic Method (Colella-Woodward)" &
1031 select case (trim(mesg))
1036 cs%useHuynh = .true.
1039 cs%useHuynh = .false.
1041 call mom_error(fatal,
"MOM_tracer_advect, tracer_advect_init: "//&
1042 "Unknown TRACER_ADVECTION_SCHEME = "//trim(mesg))
1045 id_clock_advect = cpu_clock_id(
'(Ocean advect tracer)', grain=clock_module)
1046 id_clock_pass = cpu_clock_id(
'(Ocean tracer halo updates)', grain=clock_routine)
1047 id_clock_sync = cpu_clock_id(
'(Ocean tracer global synch)', grain=clock_routine)
1049 end subroutine tracer_advect_init
1052 subroutine tracer_advect_end(CS)
1055 if (
associated(cs))
deallocate(cs)
1057 end subroutine tracer_advect_end