This subroutine does 1-d flux-form advection using a monotonic piecewise linear scheme.
704 type(ocean_grid_type),
intent(inout) :: G
705 type(verticalGrid_type),
intent(in) :: GV
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
713 type(ocean_OBC_type),
pointer :: OBC
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
723 type(unit_scale_type),
intent(in) :: US
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
757 type(OBC_segment_type),
pointer :: segment=>null()
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