#if defined(ROW_LAND) #define SEA_P .true. #define SEA_U .true. #define SEA_V .true. #elif defined(ROW_ALLSEA) #define SEA_P allip(j).or.ip(i,j).ne.0 #define SEA_U alliu(j).or.iu(i,j).ne.0 #define SEA_V alliv(j).or.iv(i,j).ne.0 #else #define SEA_P ip(i,j).ne.0 #define SEA_U iu(i,j).ne.0 #define SEA_V iv(i,j).ne.0 #endif subroutine cnuity(m,n) use mod_xc ! HYCOM communication interface use mod_cb_arrays ! HYCOM saved arrays use mod_pipe ! HYCOM debugging interface use mod_floats ! HYCOM synthetic floats, drifters and moorings #if defined(STOKES) use mod_stokes ! HYCOM Stokes drift #endif ! ! --- hycom version 1.0 implicit none ! integer m,n ! ! --- ------------------------------------------------------ ! --- continuity equation (flux-corrected transport version) ! --- ------------------------------------------------------ ! --- on entry: ! --- dp( :,:,:,n) = time step t-1 ! --- dp( :,:,:,m) = time step t ! ! --- dpv( :,:,:,n) = time step t-1 ! --- dpv( :,:,:,m) = time step t ! --- dpu( :,:,:,n) = time step t-1 ! --- dpu( :,:,:,m) = time step t ! ! --- on exit: ! --- dpo(:,:,:,n) = time step t-1 ! --- dpo(:,:,:,m) = time step t ! --- dp( :,:,:,m) = time step t with RA time smoothing ! --- dp( :,:,:,n) = time step t+1 ! ! --- onetacnt(:,:) = 1+eta afer cnuity ! --- ------------------------------------------------------ ! logical, parameter :: lpipe_cnuity=.true. !usually .false. ! real, parameter :: dpfatal=-10.0 !fatal negative dp in meters real, parameter :: epsil_cnuity=1.e-14 ! #if defined(RELO) integer, save, allocatable, dimension (:,:) :: & masku,maskv real, save, allocatable, dimension (:,:) :: & pold,oneta_u,oneta_v real, save, allocatable, dimension (:) :: & dpmn #else integer, save, dimension(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: & masku,maskv real, save, dimension(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: & pold,oneta_u,oneta_v real, save, dimension(1-nbdy:jdm+nbdy) :: & dpmn #endif ! integer i,iflip,iprint,isave,j,jsave,k,l,ia,ib,ja,jb,margin,mbdy real q,dpmin,clip,flxhi,flxlo,dtinv,dpup,dpdn,thkdfu,thkdfv real dpold,dpmid,dpnew real dpkmin(2*kdm) ! character*12 text,textu,textv ! #if defined(RELO) if (.not.allocated(masku)) then allocate( & masku(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy), & maskv(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy), & pold(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy), & oneta_u(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy), & oneta_v(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) ) call mem_stat_add( 4*(idm+2*nbdy)*(jdm+2*nbdy) ) !real=2*int masku = -99 maskv = -99 pold = r_init oneta_u = r_init oneta_v = r_init allocate( & dpmn(1-nbdy:jdm+nbdy) ) call mem_stat_add( jdm+2*nbdy ) dpmn = r_init endif ! #endif mbdy = 6 ! call xctilr(dpmixl( 1-nbdy,1-nbdy, n),1, 1, 6,6, halo_ps) call xctilr(dp( 1-nbdy,1-nbdy,1,1),1,2*kk, 6,6, halo_ps) call xctilr(dpu( 1-nbdy,1-nbdy,1,m),1, kk, 6,6, halo_us) call xctilr(dpv( 1-nbdy,1-nbdy,1,m),1, kk, 6,6, halo_vs) call xctilr(u( 1-nbdy,1-nbdy,1,m),1, kk, 6,6, halo_uv) call xctilr(v( 1-nbdy,1-nbdy,1,m),1, kk, 6,6, halo_vv) call xctilr(ubavg( 1-nbdy,1-nbdy, m),1, 1, 6,6, halo_uv) call xctilr(vbavg( 1-nbdy,1-nbdy, m),1, 1, 6,6, halo_vv) ! ! --- rhs: dpmixl.n ! --- lhs: util3, utotn, vtotn ! margin = mbdy ! !$OMP PARALLEL DO PRIVATE(j,i) & !$OMP SCHEDULE(STATIC,jblk) do j=1-margin,jj+margin do i=1-margin,ii+margin if (btrmas) then ! --- use dp, rather than dp' onetamas(i,j,:) = oneta(i,j,:) if (SEA_U) then ! --- depthu is either pbot(i,j) or pbot(i-1,j) if (pbot(i,j).eq.pbot(i-1,j)) then oneta_u(i,j) = 0.5*(onetamas(i,j,m)+onetamas(i-1,j,m)) elseif (pbot(i,j).eq.depthu(i,j)) then oneta_u(i,j) = onetamas(i,j,m) else oneta_u(i,j) = onetamas(i-1,j,m) endif endif !iu if (SEA_V) then ! --- depthv is either pbot(i,j) or pbot(i,j-1) if (pbot(i,j).eq.pbot(i,j-1)) then oneta_v(i,j) = 0.5*(onetamas(i,j,m)+onetamas(i,j-1,m)) elseif (pbot(i,j).eq.depthv(i,j)) then oneta_v(i,j) = onetamas(i,j,m) else oneta_v(i,j) = onetamas(i,j-1,m) endif endif !iv else ! --- use dp' onetamas(i,j,:) = 1.0 oneta_u(i,j) = 1.0 oneta_v(i,j) = 1.0 endif !btrmas:else utotn(i,j) = 0.0 vtotn(i,j) = 0.0 util3(i,j) = 0.0 dpmold(i,j) = dpmixl(i,j,n) ! save for Robert-Asselin filter do k= 1,kk dpo(i,j,k,n) = dp(i,j,k,n) !t-1 enddo !k enddo !i enddo !j !$OMP END PARALLEL DO ! do 76 k=1,kk ! ! --- uflux/vflux = low-order (diffusive) mass fluxes at old time level. ! --- uflux2/vflux2 = 'antidiffusive' fluxes, defined as high-order minus low- ! --- order fluxes. high-order fluxes are second-order in space, time-centered. ! ! --- rhs: depthu+, util3, dp.n, ubavg.m ! --- lhs: uflux ! margin = mbdy - 1 ! write(6,*)'cnuity.F line 96' ! do j=1-margin,jj+margin do l=1,isu(j) !ok i=ifu(j,l)-1 if (i.ge.1-margin) then if (iuopn(i,j).ne.0) then q=min(dp(i ,j,k,n),max(0.,depthu(i+1,j)-util3(i ,j))) & * onetamas(i ,j,n) utotm(i,j)=(u(i+1,j,k,m)+ubavg(i,j,m))*scuy(i,j) #if defined(STOKES) utotm(i,j)=utotm(i,j)+usd(i+1,j,k)*scuy(i,j) #endif uflux(i,j)=utotm(i,j)*q endif endif i=ilu(j,l)+1 if (i.le.ii+margin) then if (iuopn(i,j).ne.0) then q=min(dp(i-1,j,k,n),max(0.,depthu(i-1,j)-util3(i-1,j))) & * onetamas(i-1,j,n) utotm(i,j)=(u(i-1,j,k,m)+ubavg(i,j,m))*scuy(i,j) #if defined(STOKES) utotm(i,j)=utotm(i,j)+usd(i-1,j,k)*scuy(i,j) #endif uflux(i,j)=utotm(i,j)*q endif endif enddo enddo ! write(6,*)'cnuity.F line 128' ! ! --- rhs: depthv+, util3, dp.n, vbavg.m ! --- lhs: vflux ! margin = mbdy - 1 ! do i=1-margin,ii+margin do l=1,jsv(i) !ok j=jfv(i,l)-1 if (j.ge.1-margin) then if (ivopn(i,j).ne.0) then q=min(dp(i,j ,k,n),max(0.,depthv(i,j+1)-util3(i,j ))) & * onetamas(i,j ,n) vtotm(i,j)=(v(i,j+1,k,m)+vbavg(i,j,m))*scvx(i,j) #if defined(STOKES) vtotm(i,j)=vtotm(i,j)+vsd(i,j+1,k)*scvx(i,j) #endif vflux(i,j)=vtotm(i,j)*q endif endif j=jlv(i,l)+1 if (j.le.jj+margin) then if (ivopn(i,j).ne.0) then q=min(dp(i,j-1,k,n),max(0.,depthv(i,j-1)-util3(i,j-1))) & * onetamas(i,j-1,n) vtotm(i,j)=(v(i,j-1,k,m)+vbavg(i,j,m))*scvx(i,j) #if defined(STOKES) vtotm(i,j)=vtotm(i,j)+vsd(i,j-1,k)*scvx(i,j) #endif vflux(i,j)=vtotm(i,j)*q endif endif enddo enddo ! write(6,*)'cnuity.F line 165' ! ! --- rhs: u.m, ubavg.m, depthu, dp.n+, util3+, dpu.m, uflux ! --- rhs: v.m, vbavg.m, depthv, dp.n+, util3+, dpv.m, vflux ! --- lhs: utotm,uflux,uflux2,uflx ! --- lhs: vtotm,vflux,vflux2,vflx ! margin = mbdy - 1 ! !$OMP PARALLEL DO PRIVATE(j,i,q) & !$OMP SCHEDULE(STATIC,jblk) do j=1-margin,jj+margin do i=1-margin,ii+margin if (SEA_U) then utotm(i,j)=(u(i,j,k,m)+ubavg(i,j,m))*scuy(i,j) #if defined(STOKES) utotm(i,j)=utotm(i,j)+usd(i,j,k)*scuy(i,j) #endif if (utotm(i,j).ge.0.) then q=min(dp(i-1,j,k,n),max(0.,depthu(i,j)-util3(i-1,j))) & * onetamas(i-1,j,n) else q=min(dp(i ,j,k,n),max(0.,depthu(i,j)-util3(i ,j))) & * onetamas(i ,j,n) endif uflux(i,j)=utotm(i,j)*q uflux2(i,j)=utotm(i,j)*dpu(i,j,k,m)*oneta_u(i,j)- & uflux(i,j) uflx(i,j,k)=uflux(i,j) endif !iu enddo !i ! ! write(6,*)'cnuity.F line 197, j = ',j do i=1-margin,ii+margin if (SEA_V) then vtotm(i,j)=(v(i,j,k,m)+vbavg(i,j,m))*scvx(i,j) #if defined(STOKES) vtotm(i,j)=vtotm(i,j)+vsd(i,j,k)*scvx(i,j) #endif if (vtotm(i,j).ge.0.) then q=min(dp(i,j-1,k,n),max(0.,depthv(i,j)-util3(i,j-1))) & * onetamas(i,j-1,n) else q=min(dp(i,j ,k,n),max(0.,depthv(i,j)-util3(i,j ))) & * onetamas(i,j ,n) endif vflux(i,j)=vtotm(i,j)*q vflux2(i,j)=vtotm(i,j)*dpv(i,j,k,m)*oneta_v(i,j)- & vflux(i,j) vflx(i,j,k)=vflux(i,j) endif !iv enddo !i ! write(6,*)'cnuity.F line 216, j = ',j enddo !j !$OMP END PARALLEL DO ! write(6,*)'cnuity.F line 216' ! ! --- advance -dp- field using low-order (diffusive) flux values ! --- rhs: dp.n, dp.m, util3, uflux+, vflux+ ! --- lhs: dpo,util3,dp.n ! margin = mbdy - 2 ! !$OMP PARALLEL DO PRIVATE(j,i,dpmin) & !$OMP SCHEDULE(STATIC,jblk) do j=1-margin,jj+margin dpmin=999. do i=1-margin,ii+margin if (SEA_P) then util3(i,j)=util3(i,j)+dp(i,j,k,n) dp(i,j,k,n)=dp(i,j,k,n)* & onetamas(i,j,n)- & ((uflux(i+1,j)-uflux(i,j))+ & (vflux(i,j+1)-vflux(i,j)))*delt1*scp2i(i,j) dpo(i,j,k,m)=dp(i,j,k,n) ! save for loop 19 test dpmin=min(dpmin,dp(i,j,k,n)) endif !ip enddo !i dpmn(j)=dpmin ! minimizes false sharing enddo !j, loop 19 !$OMP END PARALLEL DO ! dpmin=999. do j=1,jj dpmin=min(dpmin,dpmn(j)) enddo dpkmin(k)=dpmin ! if (lpipe .and. lpipe_cnuity) then ! --- compare two model runs. write (text,'(a9,i3)') 'dp.low k=',k call pipe_compare_sym1(dp(1-nbdy,1-nbdy,k,n),ip,text) endif ! do j=1-margin,jj+margin do l=1,isu(j) !ok i=ifu(j,l)-1 if (i.ge.1-margin) then if (iuopn(i,j).ne.0) then uflux(i,j)=0.0 endif endif i=ilu(j,l)+1 if (i.le.ii+margin) then if (iuopn(i,j).ne.0) then uflux(i,j)=0.0 endif endif enddo enddo ! do i=1-margin,ii+margin do l=1,jsv(i) !ok j=jfv(i,l)-1 if (j.ge.1-margin) then if (ivopn(i,j).ne.0) then vflux(i,j)=0.0 endif endif j=jlv(i,l)+1 if (j.le.jj+margin) then if (ivopn(i,j).ne.0) then vflux(i,j)=0.0 endif endif enddo enddo ! if (lpipe .and. lpipe_cnuity) then ! --- compare two model runs. do j=1-margin,jj+margin do i=1-margin,ii+margin masku(i,j)=iu(i,j) if (i.gt. 1) masku(i,j)=masku(i,j)+iu(i-1,j) if (i.lt.ii) masku(i,j)=masku(i,j)+iu(i+1,j) maskv(i,j)=iv(i,j) if (j.gt. 1) maskv(i,j)=maskv(i,j)+iv(i,j-1) if (j.lt.jj) maskv(i,j)=maskv(i,j)+iv(i,j+1) enddo enddo write (textu,'(a9,i3)') 'uflux k=',k write (textv,'(a9,i3)') 'vflux k=',k call pipe_compare_sym2(uflux,masku,textu, & vflux,maskv,textv) write (textu,'(a9,i3)') 'uflux2 k=',k write (textv,'(a9,i3)') 'vflux2 k=',k call pipe_compare_sym2(uflux2,masku,textu, & vflux2,maskv,textv) endif ! !diag if (mod(k,15).eq.1) then !diag do i=itest-1,itest+1 !diag do j=jtest-1,jtest+1 !diag write (lp,101) nstep,i+i0,j+j0,k,dpo(i-1,j,k,n),uflux(i,j), & !diag 'old dp''s, fluxes:',dpo(i,j-1,k,n),dpo(i,j,k,n),dpo(i,j+1,k,n) & !diag ,vflux(i,j),dp(i,j,k,n),vflux(i,j+1),dpo(i+1,j,k,n),uflux(i+1,j) !diag enddo !diag enddo !diag endif 101 format (i9,2i5,i3,1p,e15.2,e30.2/a17,6e10.2/e37.2,e30.2) ! ! --- at each grid point, determine the ratio of the largest permissible ! --- pos. (neg.) change in -dp- to the sum of all incoming (outgoing) fluxes ! ! --- rhs: dp.n+, uflux2+, vflux2+ ! --- lhs: util1,util2 ! margin = mbdy - 2 ! !$OMP PARALLEL DO PRIVATE(j,i,ia,ib,ja,jb) & !$OMP SCHEDULE(STATIC,jblk) do j=1-margin,jj+margin do i=1-margin,ii+margin if (SEA_P) then ! --- assume margin