subroutine bigrid(depth, mapflg, util1,util2,util3) use mod_xc ! HYCOM communication interface implicit none ! real, dimension (1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: & depth,util1,util2,util3 integer mapflg ! ! --- set loop bounds for irregular basin in c-grid configuration ! --- q,u,v,p are vorticity, u-velocity, v-velocity, and mass points, resp. ! --- 'depth' = basin depth array, zero values indicate land ! integer nchar parameter (nchar=120) logical lperiod,larctic,lfplane ! integer i,j,nzero,isec,ifrst,ilast real rnfill,aline(nchar) real depmax character char3*3 ! character fmt*13 data fmt/'(i4,1x,120i1)'/ ! ! --- is the domain periodic in longitude? depmax=0.0 if (i0+ii.eq.itdm) then do j= 1,jj depmax=max(depmax,depth(ii,j)) enddo endif call xcmaxr(depmax) lperiod=depmax.gt.0.0 ! ! --- is the domain periodic in latitude? ! --- only allowed on f-plane or full globe (across the arctic). depmax=0.0 if (j0+jj.eq.jtdm) then do i= 1,ii depmax=max(depmax,depth(i,jj)) enddo endif call xcmaxr(depmax) larctic=depmax.gt.0.0 .and. mapflg.ne.4 lfplane=depmax.gt.0.0 .and. mapflg.eq.4 ! ! --- is this consistent with nreg (from mod_xc)? if (larctic) then if (.not.lperiod) then if (mnproc.eq.1) then write(lp,'(/a/)') & 'arctic domain, but non-periodic' call flush(lp) endif call xcstop('(bigrid)') stop '(bigrid)' else nreg = 2 endif elseif (lperiod) then if (nreg.eq.-1) then ! TYPE=one or TYPE=omp if (lfplane) then nreg = 3 ! periodic/f-plane else nreg = 1 ! periodic/closed endif elseif (nreg.eq. 0) then if (mnproc.eq.1) then write(lp,'(/a/)') & 'periodic domain, but with nreg.eq.0' call flush(lp) endif call xcstop('(bigrid)') stop '(bigrid)' endif else if (nreg.eq.-1) then ! TYPE=one or TYPE=omp if (lfplane) then nreg = 4 ! closed/f-plane else nreg = 0 ! closed/closed endif elseif (nreg.ne. 0) then if (mnproc.eq.1) then write(lp,'(/a/)') & 'closed domain, but with nreg.ne.0' call flush(lp) endif call xcstop('(bigrid)') stop '(bigrid)' endif endif ! if (mnproc.eq.1) then write(lp,'(/a,i2)') 'bigrid: nreg =',nreg if (.not.lperiod) then if (lfplane) then write(lp,'(a/)') 'bigrid: infinate closed basin' elseif (.not.larctic) then write(lp,'(a/)') 'bigrid: closed basin' else write(lp,'(a/)') 'bigrid: closed basin, arctic overlap' endif else if (lfplane) then write(lp,'(a/)') 'bigrid: doubly infinate basin' elseif (.not.larctic) then write(lp,'(a/)') 'bigrid: periodic basin' else write(lp,'(a/)') 'bigrid: global basin, arctic overlap' endif endif call flush(lp) endif ! ! --- nreg is defined, so now safe to update halo call xctilr(depth,1,1, nbdy,nbdy, halo_ps) ! ! --- allow for non-periodic and non-arctic boundaries (part I). if (.not.lfplane .and. j0.eq.0) then ! --- south boundary is all land. do j=1-nbdy,0 do i=1-nbdy,ii+nbdy depth(i,j) = 0.0 enddo enddo endif ! if (.not.lfplane .and. .not.larctic .and. j0+jj.eq.jtdm) then ! --- north boundary is all land. do j=jj+1,jj+nbdy do i=1-nbdy,ii+nbdy depth(i,j) = 0.0 enddo enddo endif ! if (.not.lperiod .and. i0.eq.0) then ! --- west boundary is all land. do j=1-nbdy,jj+nbdy do i=1-nbdy,0 depth(i,j) = 0.0 enddo enddo endif ! if (.not.lperiod .and. i0+ii.eq.itdm) then ! --- east boundary is all land. do j=1-nbdy,jj+nbdy do i=ii+1,ii+nbdy depth(i,j) = 0.0 enddo enddo endif ! ! --- detect (and abort on) single-width inlets and 1-point seas. rnfill=0.0 do j=1,jj do i=1,ii nzero=0 if (depth(i,j).gt.0.0) then if (depth(i-1,j).le.0.0) nzero=nzero+1 if (depth(i+1,j).le.0.0) nzero=nzero+1 if (depth(i,j-1).le.0.0) nzero=nzero+1 if (depth(i,j+1).le.0.0) nzero=nzero+1 !***********if (nzero.ge.3) then if (nzero.eq.4) then write (lp,'(a,i4,a,i4,a,i1,a)') & 'error - dh(',i0+i,',',j0+j,') has ', & nzero,' land nieghbours' rnfill=rnfill+1.0 elseif (nzero.eq.3) then write (lp,'(a,i4,a,i4,a,i1,a)') & 'warning - dh(',i0+i,',',j0+j,') has ', & nzero,' land nieghbours' ! rnfill=rnfill+1.0 !only a warning, don't update rnfill end if end if enddo enddo call xcsync(flush_lp) call xcmaxr(rnfill) if (rnfill.gt.0.0) then if (mnproc.eq.1) then write(lp,'(/a/)') & 'Must correct bathymetry before running HYCOM' call flush(lp) endif call xcstop('(bigrid)') stop '(bigrid)' endif ! ! --- start out with masks as land everywhere !$OMP PARALLEL DO PRIVATE(j,i) & !$OMP SCHEDULE(STATIC,jblk) do j=1-nbdy,jdm+nbdy do i=1-nbdy,idm+nbdy ip(i,j)=0 iq(i,j)=0 iu(i,j)=0 iv(i,j)=0 enddo enddo ! ! --- mass points are defined where water depth is greater than zero !$OMP PARALLEL DO PRIVATE(j,i) & !$OMP SCHEDULE(STATIC,jblk) do j=1-nbdy,jj+nbdy do i=1-nbdy,ii+nbdy if (depth(i,j).gt.0.) then ip(i,j)=1 endif enddo enddo ! ! --- u,v points are located halfway between any 2 adjoining mass points ! --- 'interior' q points require water on all 4 sides. ! --- 'promontory' q points require water on 3 (or at least 2 ! --- diametrically opposed) sides !$OMP PARALLEL DO PRIVATE(j,i) & !$OMP SCHEDULE(STATIC,jblk) do j=1,jj do i=1,ii if (ip(i-1,j).gt.0.and.ip(i,j).gt.0) then iu(i,j)=1 endif if (ip(i,j-1).gt.0.and.ip(i,j).gt.0) then iv(i,j)=1 endif if (min(ip(i,j),ip(i-1,j),ip(i,j-1),ip(i-1,j-1)).gt.0) then iq(i,j)=1 elseif ((ip(i ,j).gt.0.and.ip(i-1,j-1).gt.0).or. & (ip(i-1,j).gt.0.and.ip(i ,j-1).gt.0) ) then iq(i,j)=1 endif util1(i,j)=iu(i,j) util2(i,j)=iv(i,j) util3(i,j)=iq(i,j) enddo enddo call xctilr(util1,1,1, nbdy,nbdy, halo_us) call xctilr(util2,1,1, nbdy,nbdy, halo_vs) call xctilr(util3,1,1, nbdy,nbdy, halo_qs) !$OMP PARALLEL DO PRIVATE(j,i) & !$OMP SCHEDULE(STATIC,jblk) do j= 1-nbdy,jj+nbdy do i= 1-nbdy,ii+nbdy iu(i,j)=util1(i,j) iv(i,j)=util2(i,j) iq(i,j)=util3(i,j) enddo enddo ! ! --- allow for non-periodic and non-arctic boundaries (part II). if (.not.lfplane .and. j0.eq.0) then ! --- south boundary is all land. do j=1-nbdy,0 do i=1-nbdy,ii+nbdy iq(i,j) = 0 iu(i,j) = 0 iv(i,j) = 0 enddo enddo endif ! if (.not.lfplane .and. .not.larctic .and. j0+jj.eq.jtdm) then ! --- north boundary is all land. do j=jj+1,jj+nbdy do i=1-nbdy,ii+nbdy iq(i,j) = 0 iu(i,j) = 0 iv(i,j) = 0 enddo enddo endif ! if (.not.lperiod .and. i0.eq.0) then ! --- west boundary is all land. do j=1-nbdy,jj+nbdy do i=1-nbdy,0 iq(i,j) = 0 iu(i,j) = 0 iv(i,j) = 0 enddo enddo endif ! if (.not.lperiod .and. i0+ii.eq.itdm) then ! --- east boundary is all land. do j=1-nbdy,jj+nbdy do i=ii+1,ii+nbdy iq(i,j) = 0 iu(i,j) = 0 iv(i,j) = 0 enddo enddo endif ! ! --- logical alliX indicates entire row is sea !$OMP PARALLEL DO PRIVATE(j,i) & !$OMP SCHEDULE(STATIC,jblk) do j=1-nbdy+1,jj+nbdy-1 allip(j) = .true. alliq(j) = .true. alliu(j) = .true. alliv(j) = .true. do i=1-nbdy,ii+nbdy ! --- are all iX(:,j) sea points? allip(j) = allip(j) .and. ip(i,j).ne.0 alliq(j) = alliq(j) .and. iq(i,j).ne.0 alliu(j) = alliu(j) .and. iu(i,j).ne.0 alliv(j) = alliv(j) .and. iv(i,j).ne.0 enddo !i enddo !j ! ! --- determine sea-only i-1, i+1, j-1, and j+1 indexes !$OMP PARALLEL DO PRIVATE(j,i) & !$OMP SCHEDULE(STATIC,jblk) do j=1-nbdy+1,jj+nbdy-1 do i=1-nbdy+1,ii+nbdy-1 ! --- W,E,S,N if sea, otherwise center point if (ip(i-1,j).ne.0) then ipim1(i,j) = i-1 else ipim1(i,j) = i endif if (ip(i+1,j).ne.0) then ipip1(i,j) = i+1 else ipip1(i,j) = i endif if (ip(i,j-1).ne.0) then ipjm1(i,j) = j-1 else ipjm1(i,j) = j endif if (ip(i,j+1).ne.0) then ipjp1(i,j) = j+1 else ipjp1(i,j) = j endif ! ! --- W,E,S,N if sea, otherwise E,W,N,S if sea, otherwise center point if (ip(i-1,j).ne.0) then ipim1x(i,j) = i-1 elseif (ip(i+1,j).ne.0) then ipim1x(i,j) = i+1 else ipim1x(i,j) = i endif if (ip(i+1,j).ne.0) then ipip1x(i,j) = i+1 elseif (ip(i-1,j).ne.0) then ipip1x(i,j) = i-1 else ipip1x(i,j) = i endif if (ip(i,j-1).ne.0) then ipjm1x(i,j) = j-1 elseif (ip(i,j+1).ne.0) then ipjm1x(i,j) = j+1 else ipjm1x(i,j) = j endif if (ip(i,j+1).ne.0) then ipjp1x(i,j) = j+1 elseif (ip(i,j-1).ne.0) then ipjp1x(i,j) = j-1 else ipjp1x(i,j) = j endif enddo !i enddo !j ! ! --- determine loop bounds for vorticity points, including interior and ! --- promontory points call indxi(iq,ifq,ilq,isq) call indxj(iq,jfq,jlq,jsq) ! ! --- determine loop indices for mass and velocity points call indxi(ip,ifp,ilp,isp) call indxj(ip,jfp,jlp,jsp) call indxi(iu,ifu,ilu,isu) call indxj(iu,jfu,jlu,jsu) call indxi(iv,ifv,ilv,isv) call indxj(iv,jfv,jlv,jsv) ! ! --- write out -ip- array, if it is not too big ! --- data are written in strips nchar points wide if (max(itdm,jtdm).le.2*nchar) then util1(1:ii,1:jj) = ip(1:ii,1:jj) ! xclget is for real arrays isec=(itdm-1)/nchar do ifrst=0,nchar*isec,nchar ilast=min(itdm,ifrst+nchar) write (char3,'(i3)') ilast-ifrst fmt(8:10)=char3 if (mnproc.eq.1) then write (lp,'(a,i5,a,i5)') & 'ip array, cols',ifrst+1,' --',ilast endif do j= jtdm,1,-1 call xclget(aline,ilast-ifrst, util1,ifrst+1,j,1,0, 1) if (mnproc.eq.1) then write (lp,fmt) j,(10*nint(aline(i)),i=1,ilast-ifrst) endif enddo enddo if (mnproc.eq.1) then write (lp,*) endif call xcsync(flush_lp) endif ! small region ! return end ! ! subroutine indxi(ipt,if,il,is) use mod_xc ! HYCOM communication interface implicit none ! integer, dimension (1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: & ipt integer, dimension (1-nbdy:jdm+nbdy,ms) :: & if,il integer, dimension (1-nbdy:jdm+nbdy) :: & is ! ! --- input array ipt contains 1 at grid point locations, 0 elsewhere ! --- output is arrays if, il, is where ! --- if(j,k) gives row index of first point in column j for k-th section ! --- il(j,k) gives row index of last point ! --- is(j) gives number of sections in column j (maximum: ms) ! integer i,j,k,last ! do j=1-nbdy,jj+nbdy is(j) = 0 do k=1,ms if(j,k) = 0 il(j,k) = 0 end do ! k=1 last = ipt(1-nbdy,j) if (last .eq. 1) then if(j,k) = 1-nbdy endif do i=2-nbdy,ii+nbdy if (last .eq. 1 .and. ipt(i,j) .eq. 0) then il(j,k) = i-1 k = k+1 elseif (last .eq. 0 .and. ipt(i,j) .eq. 1) then if (k .gt. ms) then write(lp,'(a,i5)') 'indxi problem on proc ',mnproc write(lp,'(a,2i5)') & ' error in indxi -- ms too small at i,j =',i0+i,j0+j call xchalt('(indxi)') stop '(indxi)' endif if(j,k) = i endif last = ipt(i,j) enddo if (last .eq. 1) then il(j,k) = ii+nbdy is(j) = k else is(j) = k-1 endif enddo call xcsync(no_flush) return end ! subroutine indxj(jpt,jf,jl,js) use mod_xc ! HYCOM communication interface implicit none ! integer, dimension (1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) :: & jpt integer, dimension (1-nbdy:idm+nbdy,ms) :: & jf,jl integer, dimension (1-nbdy:idm+nbdy) :: & js ! ! --- input array jpt contains 1 at grid point locations, 0 elsewhere ! --- output is arrays jf, jl, js where ! --- jf(i,k) gives column index of first point in row i for k-th section ! --- jl(i,k) gives column index of last point ! --- js(i) gives number of sections in row i (maximum: ms) ! integer i,j,k,last ! do i=1-nbdy,ii+nbdy js(i) = 0 do k=1,ms jf(i,k) = 0 jl(i,k) = 0 end do ! k=1 last = jpt(i,1-nbdy) if (last .eq. 1) then jf(i,k) = 1-nbdy endif do j=2-nbdy,jj+nbdy if (last .eq. 1 .and. jpt(i,j) .eq. 0) then jl(i,k) = j-1 k = k+1 elseif (last .eq. 0 .and. jpt(i,j) .eq. 1) then if (k .gt. ms) then write(lp,'(a,i5)') 'indxj problem on proc ',mnproc write(lp,'(a,2i5)') & ' error in indxj -- ms too small at i,j =',i0+i,j0+j call xchalt('(indxj)') stop '(indxj)' endif jf(i,k) = j endif last = jpt(i,j) enddo if (last .eq. 1) then jl(i,k) = jj+nbdy js(i) = k else js(i) = k-1 endif enddo call xcsync(no_flush) return end !> !> Revision history !> !> Nov 2000 - error stop on single-width inlets and 1-point seas !> Oct 2008 - warning on single-width inlets !> May 2014 - added ipim1,ipip1,ipjm1,ipjp1,ipim1x,ipip1x,ipjm1x,ipjp1x !> May 2014 - added allip,alliq,alliu,alliv