! Generate sigma coordinates for ivcor=1 (VQS from Dukhovskoy) using ! multiple masters. ! WARNING: most variables/arrays in this program use '1' as surface, and nvrt* ! as bottom!!! ! Inputs: (1) consts. inside the code (for max. flexibility); (2) hgrid.gr3 (in map projection or lon/lat); ! (3) screen; (4) transect.bp (optional transect bp file; depths can be seg #s); ! (5) v_regions.gr3 (depths define which master grid is used ! locally. In this example, '2' is Black Sea, '1' is rest, ! and the two are smoothly stitched in middle of Bosphorus St where ! the depth <=100m, because the first 3 master grids are identical ! for h<=100m) ! Outputs: vgrid.in; vgrid_master*.out; transect1.out; debug outputs (fort*) ! Use plot_VQS.m to viz vgrid_master*.out, transect1.out ! ifort -O2 -mcmodel=medium -CB -Bstatic -o gen_vqs_2masters.exe ../UtilLib/schism_geometry.f90 gen_vqs_2masters.f90 use schism_geometry_mod implicit real*8(a-h,o-z) integer, allocatable :: elnode(:,:),elside(:,:),kbp0(:),kbp(:),ic3(:,:),isdel(:,:),isidenode(:,:),m0(:) allocatable :: xnd(:),ynd(:),dp(:),xcj(:),ycj(:),eta2(:),znd(:,:),z1tmp(:),z2tmp(:) allocatable :: hsm(:,:),nv_vqs(:,:),z_mas(:,:,:) !,a_vqs(:) allocatable :: hsm0(:),nv_vqs0(:),z_mas0(:,:) allocatable :: xybp(:,:),dpbp(:),imap(:),transect_len(:),sigma_vqs(:,:),i34(:),iflag(:),ireg(:) print*, 'Want to output along a transect? (0: no; 1:yes)' read*, itran !# of master sets used in different regions (share same m_vqs) max_m=2 !m_vqs: max # of grids/depths in each master grid m_vqs=10 dz_bot_min=3 !min. bottom layer thickness [m] allocate(hsm(max_m,m_vqs),nv_vqs(max_m,m_vqs)) !2nd master set: Black Sea hsm(2,:)=(/20.,60.,100.,140.,180.,220.,260.,2400.,3000.,4000./) nv_vqs(2,1:7)=(/15,19,23,26,29,31,33/) !# of levels for each master grid !grid #9, 10 are not used (exceed max depth of Black Sea) nv_vqs(2,8:m_vqs)=nv_vqs(2,7)+15 !1st: rest hsm(1,:)=(/20.,60.,100.,140.,300.,500.,1.e3,2.e3,3.e3,6.e3/) nv_vqs(1,1:7)=(/15,19,23,26,31,33,39/) nv_vqs(1,8)=nv_vqs(1,7)+6 nv_vqs(1,9)=nv_vqs(1,8)+5 nv_vqs(1,10)=nv_vqs(1,9)+8 if(m_vqs<2) then write(*,*)'Check vgrid.in:',m_vqs stop endif if(hsm(1,1)<0) stop 'hsm(1,1)<0' do m=2,m_vqs do i=1,max_m if(hsm(i,m)<=hsm(i,m-1)) then write(*,*)'Check hsm:',m,i,hsm(i,m),hsm(i,m-1) stop endif enddo !i enddo !m ! Other consts. ! Stretching const. for the 1st master grid (optional) ! |a_vqs0|<=1 (1: skew toward bottom; -1: toward surface; 0: no bias) a_vqs0=-1 ! Generate a master vgrid (z_mas) etal=0 !used in master grid only; elev. if(etal<=-hsm(1,1)) then write(*,*)'elevmaxval(hsm(:,m_vqs))) then print*, 'Max depth exceeds master depth:',dpmax,maxval(hsm(:,m_vqs)) stop endif call compute_nside(np,ne,i34,elnode,ns) print*, 'ns=',ns allocate(ic3(4,ne),elside(4,ne),isdel(2,ns),isidenode(2,ns),xcj(ns),ycj(ns)) call schism_geometry_double(np,ne,ns,xnd,ynd,i34,elnode,ic3,elside,isdel,isidenode,xcj,ycj) !deallocate() ! Compute zcoor znd=-1.e6 iflag=0 do i=1,np !Find master set if(ireg(i)==1) then !rest indx=1 !master set index else !Black Sea indx=2 endif !ireg(i) if(dp(i)<=hsm(indx,1)) then !shallow; compute from 1st master if(etal+hsm(indx,1)<=0) then print*, 'Check etal+hsm(1):',etal+hsm(indx,1) stop endif iflag(i)=1 kbp(i)=nv_vqs(indx,1) do k=1,nv_vqs(indx,1) !sigma=(k-1.0)/(1.0-nv_vqs(indx,1)) sigma_vqs(k,i)=(z_mas(indx,k,1)-etal)/(etal+hsm(indx,1)) znd(k,i)=sigma_vqs(k,i)*(eta2(i)+dp(i))+eta2(i) enddo !k cycle endif !Deep !Find a master vgrid m0(i)=0 do m=2,m_vqs if(dp(i)>hsm(indx,m-1).and.dp(i)<=hsm(indx,m)) then m0(i)=m zrat=(dp(i)-hsm(indx,m-1))/(hsm(indx,m)-hsm(indx,m-1)) !(0,1] exit endif enddo !m if(m0(i)==0) then print*, 'Failed to find a master vgrid:',i,dp(i) stop endif kbp(i)=0 do k=1,nv_vqs(indx,m0(i)) z1=z_mas(indx,min(k,nv_vqs(indx,m0(i)-1)),m0(i)-1) z2=z_mas(indx,k,m0(i)) z3=z1+(z2-z1)*zrat if(z3>=-dp(i)+dz_bot_min) then znd(k,i)=z3 else kbp(i)=k; exit endif enddo !k if(kbp(i)==0) then print*, 'Failed to find a bottom:',i,dp(i),z3,z_mas(indx,1:nv_vqs(indx,m0(i)),m0(i)) stop endif znd(kbp(i),i)=-dp(i) !Check order do k=2,kbp(i) if(znd(k-1,i)<=znd(k,i)) then print*, 'Inverted z:',i,dp(i),m0(i),k,znd(k-1,i),znd(k,i) stop endif enddo !k write(99,*)'Node:',i,real(dp(i)),real(znd(1:kbp(i),i)) enddo !i=1,np ! Extend beyond bottom for plotting do i=1,np znd(kbp(i)+1:nvrt,i)=-dp(i) enddo !i ! Optional output along transect if(itran/=0) then open(9,file='transect.bp',status='old') read(9,*) read(9,*)npbp allocate(xybp(2,npbp),dpbp(npbp),imap(npbp),transect_len(npbp)) transect_len(1)=0 !along transect distance do i=1,npbp read(9,*)j,xybp(1:2,i),dpbp(i) if(i>1) then rl=sqrt((xybp(1,i)-xybp(1,i-1))**2+(xybp(2,i)-xybp(2,i-1))**2) transect_len(i)=transect_len(i-1)+rl endif enddo !i close(9) !Find nearest node do i=1,npbp rlmin=huge(1.0d0) do j=1,np rl2=(xybp(1,i)-xnd(j))**2+(xybp(2,i)-ynd(j))**2 if(rl210000000) stop 'Please increase write length' write(19,'(10000000(1x,i10))')nvrt+1-kbp(:) do i=1,np ! if(dp(i)<=hsm(1)) then if(iflag(i)/=0) then !sigma_vqs already assigned else sigma_vqs(1,i)=0 sigma_vqs(kbp(i),i)=-1 do k=2,kbp(i)-1 sigma_vqs(k,i)=(znd(k,i)-eta2(i))/(eta2(i)+dp(i)) enddo !k endif !Check order do k=2,kbp(i) if(sigma_vqs(k,i)>=sigma_vqs(k-1,i)) then print*, 'Inverted sigma:',i,k,dp(i),sigma_vqs(k,i),sigma_vqs(k-1,i) stop endif enddo !k ! write(19,'(2(1x,i10),10000(1x,f14.6))')i,nvrt+1-kbp(i),sigma_vqs(kbp(i):1:-1,i) enddo !i do k=1,nvrt write(19,'(i10,10000000(1x,f14.6))')k,(sigma_vqs(nvrt+1-k,i),i=1,np) enddo !k close(19) ! Output horizontal map of # of levels for more adjustment open(13,file='nlev.gr3',status='replace') write(13,*)'# of levels at each node' write(13,*)ne,np do i=1,np write(13,*)i,xnd(i),ynd(i),kbp(i) enddo !i do i=1,ne write(13,*)i,i34(i),elnode(1:i34(i),i) enddo !i close(13) stop end