#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 diapf1(m,n) use mod_xc ! HYCOM communication interface use mod_cb_arrays ! HYCOM saved arrays ! ! --- hycom version 1.0 ! --- KPP-style implicit interior diapycnal mixing implicit none ! integer m,n ! ! -------------------- ! --- diapycnal mixing ! -------------------- ! ! --- interior diapycnal mixing due to three processes: ! --- shear instability ! --- double diffusion ! --- background internal waves ! ! --- this is essentially the k-profile-parameterization (kpp) mixing model ! --- (mxkpp.f) with all surface boundary layer processes removed ! ! --- uses the same tri-diagonal matrix solution of vertical diffusion ! --- equation as mxkpp.f ! integer j ! if (mod(nstep, mixfrq).ne.0 .and. & mod(nstep+1,mixfrq).ne.0 ) then return ! diapycnal mixing only every mixfrq,mixfrq+1 time steps endif ! call xctilr(u(1-nbdy,1-nbdy,1,n),1,kk, 1,1, halo_uv) call xctilr(v(1-nbdy,1-nbdy,1,n),1,kk, 1,1, halo_vv) call xctilr(p(1-nbdy,1-nbdy,2 ),1,kk, 1,1, halo_ps) ! !$OMP PARALLEL DO PRIVATE(j) & !$OMP SHARED(m,n) & !$OMP SCHEDULE(STATIC,jblk) do j=1,jj call diapf1aj(m,n, j) enddo !$OMP END PARALLEL DO ! ! --- momentum mixing ! call xctilr(vcty(1-nbdy,1-nbdy,2),1,kk, 1,1, halo_ps) ! !$OMP PARALLEL DO PRIVATE(j) & !$OMP SHARED(m,n) & !$OMP SCHEDULE(STATIC,jblk) do j=1,jj call diapf1bj(m,n, j) enddo !$OMP END PARALLEL DO ! return end subroutine diapf1aj(m,n, j) use mod_xc ! HYCOM communication interface use mod_cb_arrays ! HYCOM saved arrays implicit none ! integer m,n, j integer i ! do i=1,ii if (SEA_P) then call diapf1aij(m,n, i,j) endif !ip enddo !i ! return end subroutine diapf1bj(m,n, j) use mod_xc ! HYCOM communication interface use mod_cb_arrays ! HYCOM saved arrays implicit none ! integer m,n, j integer i ! do i=1,ii if (SEA_U) then call diapf1uij(m,n, i,j) endif !iu if (SEA_V) then call diapf1vij(m,n, i,j) endif !iv enddo !i ! return end subroutine diapf1aij(m,n, i,j) use mod_xc ! HYCOM communication interface use mod_cb_arrays ! HYCOM saved arrays #if defined(STOKES) use mod_stokes ! HYCOM Stokes drift #endif ! ! --- hycom version 1.0 ! --- KPP-style implicit interior diapycnal mixing implicit none ! integer m,n, i,j ! ! ----------------------------------------------- ! --- diapycnal mixing, single i,j point (part A) ! ----------------------------------------------- ! ! --- interior diapycnal mixing due to three processes: ! --- shear instability ! --- double diffusion ! --- background internal waves ! ! --- this is essentially the k-profile-parameterization (kpp) mixing model ! --- (mxkpp.f) with all surface boundary layer processes removed ! ! --- uses the same tri-diagonal matrix solution of vertical diffusion ! --- equation as mxkpp.f ! ! local variables for kpp mixing real shsq(kdm+1) ! velocity shear squared real alfadt(kdm+1) ! t contribution to density jump real betads(kdm+1) ! s contribution to density jump real dbloc(kdm+1) ! buoyancy jump across interface real hwide(kdm) ! layer thicknesses in m real rrho ! double diffusion parameter real diffdd ! double diffusion diffusivity scale real prandtl ! prandtl number real rigr ! local richardson number real fri ! function of Rig for KPP shear instability real dflsiw ! wave diffusivity real dflmiw ! wave viscosity real dflbot(kdm+1) ! bottom intensified background viscosity ! ! --- local 1-d arrays for matrix inversion real t1do(kdm+1),t1dn(kdm+1),s1do(kdm+1),s1dn(kdm+1), & tr1do(kdm+1,mxtrcr),tr1dn(kdm+1,mxtrcr), & difft(kdm+1),diffs(kdm+1),difftr(kdm+1), & zm(kdm+1),hm(kdm),dzb(kdm) ! ! --- tridiagonal matrix solution arrays real tri(kdm,0:1) ! dt/dz/dz factors in trid. matrix real tcu(kdm), & ! upper coeff for (k-1) on k line of trid.matrix tcc(kdm), & ! central ... (k ) .. tcl(kdm), & ! lower ..... (k-1) .. rhs(kdm) ! right-hand-side terms ! real ratio,froglp,q,wq,wt,wz0,wz1,wz2 integer k,k1,ka,kmask,ktr,nlayer,mixflg real riv_input ! real, parameter :: difriv = 50.0e-4 !river diffusion ! # include "stmt_fns.h" froglp=.5*max(2,mixfrq) ! ! --- internal wave diffusion/viscosity dflsiw = diws(i,j) dflmiw = diwm(i,j) ! ! --- locate lowest substantial mass-containing layer. avoid near-zero ! --- thickness layers near the bottom klist(i,j)=0 kmask=0 ! do k=1,kk p(i,j,k+1)=p(i,j,k)+dp(i,j,k,n) if (dp(i,j,k,n).lt.onemm) kmask=1 if (p(i,j,k).lt.p(i,j,kk+1)-onem.and.kmask.eq.0) klist(i,j)=k enddo ! ! --- dflbot (Prandtl number of one, i.e. diffusion = viscosity) if (botdiw) then ! --- diffusion coefficent profile is: K = Kb / (1 + h/h0)**2 ! --- where diwbot = Kb; diwqh0 = 1/h0 (input as h0, see forfun.f) ! --- Decloedt T. and D.S. Luther, 2009: On a Simple Empirical ! --- Parameterization of Topography-Catalyzed Diapycnal Mixing ! --- in the Abyssal Ocean. JPO, 40, pp 487-508. ! --- use Simpson's rule to estimate the average K across each layer wz0 = 1.0 / (1.0 + (p(i,j,kk+1)- p(i,j,1) )*diwqh0(i,j))**2 wz1 = 1.0 / (1.0 + (p(i,j,kk+1)-0.5*(p(i,j,1)+ & p(i,j,2) ))*diwqh0(i,j))**2 wz2 = 1.0 / (1.0 + (p(i,j,kk+1)- p(i,j,2) )*diwqh0(i,j))**2 wq = wz0 + wz2 + 4.0*wz1 !6 times the average value over layer 1 do k= 2,kk wt = wq wz0 = wz2 wz1 = 1.0 / (1.0 + (p(i,j,kk+1) - & 0.5*(p(i,j,k) + & p(i,j,k+1) ))*diwqh0(i,j))**2 wz2 = 1.0 / (1.0 + (p(i,j,kk+1) - & p(i,j,k+1) )*diwqh0(i,j))**2 wq = wz0 + wz2 + 4.0*wz1 !6 times the average value over layer k dflbot(k) = (0.5/6.0)*(wt+wq)*diwbot(i,j) enddo dflbot(kk+1) = dflbot(kk) else do k= 2,kk+1 dflbot(k) = 0.0 enddo endif !botdiw ! ! --- calculate vertical grid and layer widths do k=1,kk if (k.eq.1) then hwide(k)=dp(i,j,k,n)*qonem zgrid(i,j,k)=-.5*hwide(k) elseif (k.lt.klist(i,j)) then hwide(k)=dp(i,j,k,n)*qonem zgrid(i,j,k)=zgrid(i,j,k-1)-.5*(hwide(k-1)+hwide(k)) elseif (k.eq.klist(i,j)) then hwide(k)=dp(i,j,k,n)*qonem zgrid(i,j,k)=zgrid(i,j,k-1)-.5*(hwide(k-1)+hwide(k)) zgrid(i,j,k+1)=zgrid(i,j,k)-.5*hwide(k) else hwide(k)=0. endif enddo ! ! --- calculate interface variables required to estimate interior diffusivities do k=1,kk k1= k+1 ka=min(k+1,kk) if (k.le.klist(i,j)) then #if defined(STOKES) !DAN========================================================================== !DAN U and V Stokes Drift Layer Average Velocities addes to Shear calculation !DAN shsq(k1)=(u(i,j,k, n)+u(i+1,j,k, n)+usd(i,j,k)+usd(i+1,j,k)- & u(i,j,ka,n)-usd(i+1,j,ka)-u(i,j,ka,n)-usd(i+1,j,ka))**2+ & (v(i,j,k, n)+v(i,j+1,k, n)+vsd(i,j,k)+vsd(i,j+1,k)- & v(i,j,ka,n)-v(i,j+1,ka,n)-vsd(i,j,ka)-vsd(i,j+1,ka))**2 #else shsq( k1)=(u(i,j,k, n)+u(i+1,j,k, n)- & u(i,j,ka,n)-u(i+1,j,ka,n))**2+ & (v(i,j,k, n)+v(i,j+1,k, n)- & v(i,j,ka,n)-v(i,j+1,ka,n))**2 #endif if (locsig) then alfadt(k1)=dsiglocdt(ahalf*(temp(i,j,k ,n)+ & temp(i,j,ka,n) ), & ahalf*(saln(i,j,k, n)+ & saln(i,j,ka,n) ),p(i,j,k1))* & (temp(i,j,k ,n)- & temp(i,j,ka,n) ) betads(k1)=dsiglocds(ahalf*(temp(i,j,k ,n)+ & temp(i,j,ka,n) ), & ahalf*(saln(i,j,k, n)+ & saln(i,j,ka,n) ),p(i,j,k1))* & (saln(i,j,k ,n)- & saln(i,j,ka,n) ) else alfadt(k1)=dsigdt(ahalf*(temp(i,j,k ,n)+ & temp(i,j,ka,n) ), & ahalf*(saln(i,j,k, n)+ & saln(i,j,ka,n) ) )* & (temp(i,j,k ,n)- & temp(i,j,ka,n) ) betads(k1)=dsigds(ahalf*(temp(i,j,k ,n)+ & temp(i,j,ka,n) ), & ahalf*(saln(i,j,k, n)+ & saln(i,j,ka,n) ) )* & (saln(i,j,k ,n)- & saln(i,j,ka,n) ) endif dbloc(k1)=-g*svref*(alfadt(k1)+betads(k1)) endif enddo ! ! --- determine interior diffusivity profiles throughout the water column ! --- limit mixing to the stratified interior of the ocean ! do k=1,kk+1 vcty(i,j,k)=0. dift(i,j,k)=0. difs(i,j,k)=0. enddo ! ! --- shear instability plus background internal wave contributions do k=2,kk+1 if (k-1.le.klist(i,j) .and. p(i,j,k).gt.dpmixl(i,j,n)) then if (shinst) then q =zgrid(i,j,k-1)-zgrid(i,j,k) !0.5*(hwide(k-1)+hwide(k)) rigr=max(0.0,dbloc(k)*q/(shsq(k)+epsil)) ratio=min(rigr*qrinfy,1.0) fri=(1.0-ratio*ratio) fri=fri*fri*fri vcty(i,j,k)=difm0*fri+dflmiw+dflbot(k) difs(i,j,k)=difs0*fri+dflsiw+dflbot(k) dift(i,j,k)=difs(i,j,k) else vcty(i,j,k)=dflmiw+dflbot(k) difs(i,j,k)=dflsiw+dflbot(k) dift(i,j,k)=dflsiw+dflbot(k) endif endif enddo ! ! --- double-diffusion (salt fingering and diffusive convection) if (dbdiff) then do k=2,kk+1 if (k-1.le.klist(i,j) .and. p(i,j,k).gt.dpmixl(i,j,n)) then ! ! --- salt fingering case if (-alfadt(k).gt.betads(k) .and. betads(k).gt.0.) then rrho= min(-alfadt(k)/betads(k),rrho0) diffdd=1.-((rrho-1.)/(rrho0-1.))**2 diffdd=dsfmax*diffdd*diffdd*diffdd dift(i,j,k)=dift(i,j,k)+0.7*diffdd difs(i,j,k)=difs(i,j,k)+diffdd ! ! --- diffusive convection case elseif (alfadt(k).gt.0.0 .and. betads(k).lt.0.0 .and. & -alfadt(k).gt.betads(k)) then rrho=-alfadt(k)/betads(k) diffdd=1.5e-6*9.*.101*exp(4.6*exp(-.54*(1./rrho-1.))) prandtl=.15*rrho if (rrho.gt..5) prandtl=(1.85-.85/rrho)*rrho dift(i,j,k)=dift(i,j,k)+diffdd difs(i,j,k)=difs(i,j,k)+prandtl*diffdd endif endif enddo endif ! !diag if (i.eq.itest.and.j.eq.jtest) write (lp,101) & !diag (nstep,i+i0,j+i0,k, & !diag hwide(k),1.e4*vcty(i,j,k),1.e4*dift(i,j,k), & !diag 1.e4*difs(i,j,k),k=1,kk+1) ! ! --- perform the vertical mixing at p points ! mixflg=0 do k=1,klist(i,j) if (dift(i,j,k+1).gt.0. .or. & difs(i,j,k+1).gt.0.) mixflg=mixflg+1 difft( k+1)=froglp*dift(i,j,k+1) diffs( k+1)=froglp*difs(i,j,k+1) difftr(k+1)=froglp*difs(i,j,k+1) t1do(k)=temp(i,j,k,n) s1do(k)=saln(i,j,k,n) do ktr= 1,ntracr tr1do(k,ktr)=tracer(i,j,k,n,ktr) enddo hm(k)=hwide(k) zm(k)=zgrid(i,j,k) enddo ! if (mixflg.le.1) return nlayer=klist(i,j) k=nlayer+1 ka=min(k,kk) difft( k)=0. diffs( k)=0. difftr(k)=0. t1do(k)=temp(i,j,ka,n) s1do(k)=saln(i,j,ka,n) do ktr= 1,ntracr tr1do(k,ktr)=tracer(i,j,ka,n,ktr) enddo zm(k)=zgrid(i,j,k) ! ! --- do rivers here because difs is also used for tracers. #if defined (USE_NUOPC_CESMBETA) if(cpl_orivers.and.cpl_irivers) then riv_input = imp_orivers(i,j,1)+imp_irivers(i,j,1) else riv_input = rivers(i,j,1) endif #else riv_input = rivers(i,j,1) #endif if (thkriv.gt.0.0 .and. riv_input.ne.0.0) then do k=1,nlayer if (-zm(k)+0.5*hm(k).lt.thkriv) then !interface 1, apply mixing algorithm to both time levels froglp=max(2,mixfrq) ! do i=1,ii if (SEA_P) then ! ! --- t/s conservation diagnostics (optional): ! totem(i)=0. ! tosal(i)=0. ! do k=1,kk ! totem(i)=totem(i)+temp(i,j,k,n)*dp(i,j,k,n) ! tosal(i)=tosal(i)+saln(i,j,k,n)*dp(i,j,k,n) ! enddo ! do k=1,kk p(i,j,k+1)=p(i,j,k)+dp(i,j,k,n) enddo !k ! sold(i,1)=saln(i,j,kk,n) told(i,1)=temp(i,j,kk,n) tflxl(i, 0)=0. tflxu(i,kk+1)=0. sflxl(i, 0)=0. sflxu(i,kk+1)=0. do ktr= 1,ntracr trold( i, 1,ktr)=tracer(i,j,kk,n,ktr) trflxl(i, 0,ktr)=0. trflxu(i,kk+1,ktr)=0. enddo !ktr ! !diag if (i.eq.itest.and.j.eq.jtest) & !diag write (lp,'(i9,2i5,3x,a/(i36,4f10.3))') nstep,i+i0,j+j0, & !diag 'before diapf2: thickness salinity temperature density', & !diag (k,dp(i,j,k,n)*qonem,saln(i,j,k,n), & !diag temp(i,j,k,n),th3d(i,j,k,n)+thbase,k=1,kk) ! kmin(i)=kk+1 kmax(i)=1 ! do k=2,kk ! ! --- locate lowest mass-containing layer and upper edge of stratified region if (p(i,j,k).lt.p(i,j,kk+1)-onemm) then kmax(i)=k if (kmin(i).eq.kk+1 .and. & th3d(i,j,k,n).gt.th3d(i,j,k-1,n)+sigjmp) then kmin(i)=k endif endif enddo !k ! !diag if (j.eq.jtest.and.itest.ge.ifp(j,l).and.itest.le.ilp(j,l)) & !diag write (lp,'(i9,2i5,a,2i5)') & !diag nstep,itest+i0,j+j0,' kmin,kmax =',kmin(itest),kmax(itest) ! ! --- find buoyancy frequency for each layer ! do k=2,kk-1 k1=k-1 k2=k+1 ! if (k.gt.kmin(i) .and. k.lt.kmax(i)) then ! --- ennsq = buoy.freq.^2 / g^2 if (locsig) then alfadt1=dsiglocdt(ahalf*(temp(i,j,k1,n)+ & temp(i,j,k ,n) ), & ahalf*(saln(i,j,k1,n)+ & saln(i,j,k, n) ),p(i,j,k))* & (temp(i,j,k1,n)- & temp(i,j,k, n) ) betads1=dsiglocds(ahalf*(temp(i,j,k1,n)+ & temp(i,j,k ,n) ), & ahalf*(saln(i,j,k1,n)+ & saln(i,j,k, n) ),p(i,j,k))* & (saln(i,j,k1,n)- & saln(i,j,k, n) ) alfadt2=dsiglocdt(ahalf*(temp(i,j,k ,n)+ & temp(i,j,k2,n) ), & ahalf*(saln(i,j,k ,n)+ & saln(i,j,k2,n) ),p(i,j,k2))* & (temp(i,j,k, n)- & temp(i,j,k2,n) ) betads2=dsiglocdt(ahalf*(temp(i,j,k ,n)+ & temp(i,j,k2,n) ), & ahalf*(saln(i,j,k ,n)+ & saln(i,j,k2,n) ),p(i,j,k2))* & (saln(i,j,k, n)- & saln(i,j,k2,n) ) ennsq=-min(0.,min(alfadt1+betads1,alfadt2+betads2)) & /max(p(i,j,k2)-p(i,j,k),onem) else ennsq=max(0.,min(th3d(i,j,k2,n)-th3d(i,j,k ,n), & th3d(i,j,k ,n)-th3d(i,j,k1,n))) & /max(p(i,j,k2)-p(i,j,k),onem) endif ! --- store (exch.coeff x buoy.freq.^2 / g x time step) in -flngth- ! --- (dimensions of flngth: length in pressure units) ! ----------------------------------------------------------------------- ! --- use the following if exch.coeff. = diapyc / buoyancy frequency flngth(i,k)=diapyc*sqrt(ennsq) * baclin*froglp * onem ! ----------------------------------------------------------------------- ! --- use the following if exch.coeff. = diapyc !cc flngth(i,k)=diapyc*ennsq*g * baclin*froglp * onem ! ----------------------------------------------------------------------- ! endif enddo !k ! ! --- find t/s fluxes at the upper and lower interface of each layer ! --- (compute only the part common to t and s fluxes) ! do k=1,kk flxu(i,k)=0. flxl(i,k)=0. ! if (k.gt.kmin(i) .and. k.lt.kmax(i)) then ! if (locsig) then plev=p(i,j,k)+0.5*dp(i,j,k,n) alfa=-svref*dsiglocdt(temp(i,j,k,n),saln(i,j,k,n),plev) beta= svref*dsiglocds(temp(i,j,k,n),saln(i,j,k,n),plev) else alfa=-svref*dsigdt(temp(i,j,k,n),saln(i,j,k,n)) beta= svref*dsigds(temp(i,j,k,n),saln(i,j,k,n)) endif ! flxu(i,k)=flngth(i,k)/ & max(beta*(saln(i,j,k,n)-saln(i,j,k-1,n)) & -alfa*(temp(i,j,k,n)-temp(i,j,k-1,n)),small) flxl(i,k)=flngth(i,k)/ & max(beta*(saln(i,j,k+1,n)-saln(i,j,k,n)) & -alfa*(temp(i,j,k+1,n)-temp(i,j,k,n)),small) ! q=min(1.,.5*min(p(i,j,k)-p(i,j,k-1),p(i,j,k+2)-p(i,j,k+1))/ & max(flxu(i,k),flxl(i,k),epsil)) ! !diag if (q.ne.1.) write (lp,'(i9,2i5,i3,a,1p,2e10.2,0p,2f7.2,f5.2)') & !diag nstep,i+i0,j+j0,k,' flxu/l,dpu/l,q=',flxu(i,k),flxl(i,k), & !diag (p(i,j,k)-p(i,j,k-1))*qonem,(p(i,j,k+2)-p(i,j,k+1))*qonem,q ! flxu(i,k)=flxu(i,k)*q flxl(i,k)=flxl(i,k)*q ! endif ! kmin < k < kmax ! !diag if (i.eq.itest.and.j.eq.jtest.and.k.ge.kmin(i).and.k.le.kmax(i)) & !diag write (lp,'(i9,2i5,i3,3x,a/22x,f9.3,2f7.3,1p,3e10.3)') & !diag nstep,i+i0,j+j0,k, & !diag 'thknss temp saln flngth flxu flxl', & !diag dp(i,j,k,n)*qonem,temp(i,j,k,n),saln(i,j,k,n),flngth(i,k), & !diag flxu(i,k)*qonem,flxl(i,k)*qonem ! enddo !k ! ! --- determine mass flux -pdot- implied by t/s fluxes. ! do k=1,kk if (k.gt.kmin(i) .and. k.le.kmax(i)) then pdot(i,k)=flxu(i,k)-flxl(i,k-1) else pdot(i,k)=0. endif enddo !k ! ! --- convert flxu,flxl into actual t/s (and tracer) fluxes ! do k=1,kk tflxu(i,k)=0. tflxl(i,k)=0. sflxu(i,k)=0. sflxl(i,k)=0. if (k.gt.kmin(i) .and. k.lt.kmax(i)) then tflxu(i,k)=flxu(i,k)*temp(i,j,k-1,n) sflxu(i,k)=flxu(i,k)*saln(i,j,k-1,n) ! tflxl(i,k)=flxl(i,k)*temp(i,j,k+1,n) sflxl(i,k)=flxl(i,k)*saln(i,j,k+1,n) endif do ktr= 1,ntracr trflxu(i,k,ktr)=0. trflxl(i,k,ktr)=0. if (k.gt.kmin(i) .and. k.lt.kmax(i)) then trflxu(i,k,ktr)=flxu(i,k)*tracer(i,j,k-1,n,ktr) trflxl(i,k,ktr)=flxl(i,k)*tracer(i,j,k+1,n,ktr) endif enddo !ktr enddo !k ! do ktr= 1,ntracr cliptr(i,ktr)=0. enddo !ktr clipt( i)=0. clips( i)=0. ! ! --- update interface pressure and layer temperature/salinity do k=kk,1,-1 ka=max(1,k-1) ! sold(i,2)=sold(i,1) sold(i,1)=saln(i,j,k,n) told(i,2)=told(i,1) told(i,1)=temp(i,j,k,n) do ktr= 1,ntracr trold(i,2,ktr)=trold( i,1, ktr) trold(i,1,ktr)=tracer(i,j,k,n,ktr) enddo ! dpo(i,j,k,n)=dp(i,j,k,n) p(i,j,k)=p(i,j,k)-pdot(i,k) dp(i,j,k,n)=p(i,j,k+1)-p(i,j,k) ! if (k.ge.kmin(i) .and. k.le.kmax(i)) then delp=dp(i,j,k,n) if (delp.gt.0.) then amount=temp(i,j,k,n)*dpo(i,j,k,n) & -(tflxu(i,k+1)-tflxu(i,k)+tflxl(i,k-1)-tflxl(i,k)) q=amount qmax=max(temp(i,j,ka,n),told(i,1),told(i,2)) qmin=min(temp(i,j,ka,n),told(i,1),told(i,2)) amount=max(qmin*delp,min(amount,qmax*delp)) clipt(i)=clipt(i)+(q-amount) temp(i,j,k,n)=amount/delp ! amount=saln(i,j,k,n)*dpo(i,j,k,n) & -(sflxu(i,k+1)-sflxu(i,k)+sflxl(i,k-1)-sflxl(i,k)) q=amount qmax=max(saln(i,j,ka,n),sold(i,1),sold(i,2)) qmin=min(saln(i,j,ka,n),sold(i,1),sold(i,2)) amount=max(qmin*delp,min(amount,qmax*delp)) clips(i)=clips(i)+(q-amount) saln(i,j,k,n)=amount/delp ! do ktr= 1,ntracr amount=tracer(i,j,k,n,ktr)*dpo(i,j,k,n) & -(trflxu(i,k+1,ktr)-trflxu(i,k,ktr)+ & trflxl(i,k-1,ktr)-trflxl(i,k,ktr)) q=amount qmax=max(tracer(i,j,ka,n,ktr),trold(i,1,ktr), & trold(i,2,ktr)) qmin=min(tracer(i,j,ka,n,ktr),trold(i,1,ktr), & trold(i,2,ktr)) amount=max(qmin*delp,min(amount,qmax*delp)) cliptr(i,ktr)=cliptr(i,ktr)+(q-amount) tracer(i,j,k,n,ktr)=amount/delp enddo !ktr endif endif enddo !k ! clipt(i)=clipt(i)/pbot(i,j) + baclin*froglp*tofset clips(i)=clips(i)/pbot(i,j) + baclin*froglp*sofset do ktr= 1,ntracr cliptr(i,ktr)=cliptr(i,ktr)/pbot(i,j) enddo !ktr ! do k=1,kk ! ! --- restore 'clipped' and 'offset' t/s amount to column temp(i,j,k,n)=temp(i,j,k,n)+clipt(i) saln(i,j,k,n)=saln(i,j,k,n)+clips(i) th3d(i,j,k,n)=sig(temp(i,j,k,n),saln(i,j,k,n))-thbase do ktr= 1,ntracr tracer(i,j,k,n,ktr)=tracer(i,j,k,n,ktr)+cliptr(i,ktr) enddo !ktr ! diaflx(i,j,k)=diaflx(i,j,k)+(dp(i,j,k,n)-dpo(i,j,k,n)) ! diapyc.flx. ! --- make sure p is computed from dp, not the other way around (roundoff!) p(i,j,k+1)=p(i,j,k)+dp(i,j,k,n) enddo !k ! ! --- t/s conservation diagnostics (optional): ! tndcyt=-totem(i) ! tndcys=-tosal(i) ! do k=1,kk ! tndcyt=tndcyt+temp(i,j,k,n)*dp(i,j,k,n) ! tndcys=tndcys+saln(i,j,k,n)*dp(i,j,k,n) ! enddo ! if (abs(tndcyt/totem(i)).gt.1.e-11) ! . write (lp,100) i,j,' diapf2 temp.col.intgl.:',totem(i),tndcyt, ! . clipt(i) ! if (abs(tndcys/tosal(i)).gt.1.e-11) ! . write (lp,100) ! . i+i0,j+i0,' diapf2 saln.col.intgl.:',tosal(i),tndcys,clips(i) !100 format(2i5,a,1p,e16.8,2e13.5) ! !diag if (i.eq.itest.and.j.eq.jtest) & !diag write (lp,'(i9,2i5,3x,a/(i36,0p,4f10.3))') & !diag nstep,i+i0,j+j0, & !diag 'after diapf2: thickness salinity temperature density', & !diag (k,dp(i,j,k,n)*qonem,saln(i,j,k,n), & !diag temp(i,j,k,n),th3d(i,j,k,n)+thbase,k=1,kk) ! endif !ip enddo !i ! return end ! subroutine diapf3(m,n) use mod_xc ! HYCOM communication interface use mod_cb_arrays ! HYCOM saved arrays ! ! --- hycom version 1.0 (adapted from micom version 2.8) ! --- MICOM-style explict interior diapycnal mixing for isopycnal coords implicit none ! integer m,n ! integer j ! if (diapyc.eq.0. .or. (mod(nstep ,mixfrq).ne.0 .and. & mod(nstep+1,mixfrq).ne.0)) return !diag write (lp,'(i9,3x,a)') nstep,'entering d i a p f l' ! !$OMP PARALLEL DO PRIVATE(j) & !$OMP SHARED(m,n) & !$OMP SCHEDULE(STATIC,jblk) do 31 j=1,jj call diapf3j(m,n, j) 31 continue ! call dpudpv(dpu(1-nbdy,1-nbdy,1,n), & dpv(1-nbdy,1-nbdy,1,n), & p,depthu,depthv, 0,0) ! !diag write (lp,'(i9,3x,a)') nstep,'exiting d i a p f l' return end subroutine diapf3j(m,n, j) use mod_xc ! HYCOM communication interface use mod_cb_arrays ! HYCOM saved arrays ! ! --- hycom version 1.0 (adapted from micom version 2.8) ! --- MICOM-style explict interior diapycnal mixing for isopycnic coordinates implicit none ! integer m,n,j ! integer i,k,k1,k2,ktr,l integer kmin(idm),kmax(idm) real flxu(idm,kdm),flxl(idm,kdm),pdot(idm,kdm),flngth(idm,kdm), & ennsq,alfa,beta,smax,smin,sold(idm,2),q,salt,froglp, & alfadt1,alfadt2,betads1,betads2,plev, & flxtru(idm,kdm,mxtrcr), & flxtrl(idm,kdm,mxtrcr),trold(idm,2,mxtrcr),trmax,trmin ! real small parameter (small=1.e-6) ! # include "stmt_fns.h" ! ! --- ------------------------------ ! --- diapycnal mixing, single j-row. ! --- ------------------------------- ! ! --- if mixfrq > 1, apply mixing algorithm to both time levels froglp=max(2,mixfrq) ! !cc salt=0. ! do i=1,ii if (SEA_P) then ! do k=1,kk p(i,j,k+1)=p(i,j,k)+dp(i,j,k,n) enddo !k ! sold(i,1)=saln(i,j,kk,n) do ktr= 1,ntracr trold(i,1,ktr)=tracer(i,j,kk,n,ktr) enddo !ktr flxl(i,1)=0. ! !diag if (i.eq.itest .and. j.eq.jtest) & !diag write (lp,'(i9,2i5,3x,a/(i36,0p,3f10.3,3p,f10.3))') & !diag nstep,i+i0,j+j0, & !diag 'before diapfl: thickness salinity temperature density', & !diag 1,dp(i,j,1,n)*qonem,saln(i,j,1,n),temp(i,j,1,n), & !diag th3d(i,j,1,n)+thbase,(k,dp(i,j,k,n)*qonem,saln(i,j,k,n), & !diag temp(i,j,k,n),th3d(i,j,k,n)+thbase,k=2,kk) ! kmin(i)=kk+1 kmax(i)=1 ! do k=2,kk ! ! --- locate lowest mass-containing layer if (p(i,j,k).lt.p(i,j,kk+1)) then kmax(i)=k ! ! --- make sure salinity is compatible with density in layer k !cc q=sofsig(th3d(i,j,k,n)+thbase,temp(i,j,k,n)) !cc salt=salt+(q-saln(i,j,k,n))*dp(i,j,k,n)*scp2(i) !cc saln(i,j,k,n)=q ! ! --- locate uppermost isopycnic layer heavier than mixed layer if (kmin(i).eq.kk+1 .and. & max(th3d(i,j,1,m),th3d(i,j,1,n))+sigjmp.le.th3d(i,j,k,n)) & kmin(i)=k end if enddo !k ! !diag if (j.eq.jtest.and.itest.ge.ifp(j,l).and.itest.le.ilp(j,l)) & !diag write (lp,'(i9,2i5,a,2i5)') & !diag nstep,itest+i0,j+j0,' kmin,kmax =',kmin(itest),kmax(itest) ! ! --- temporarily swap layers 1 and kmin-1 ! do k=3,kk if (k.eq.kmin(i)) then q=temp(i,j,k-1,n) temp(i,j,k-1,n)=temp(i,j,1,n) temp(i,j,1,n)=q ! q=saln(i,j,k-1,n) saln(i,j,k-1,n)=saln(i,j,1,n) saln(i,j,1,n)=q ! q=th3d(i,j,k-1,n) th3d(i,j,k-1,n)=th3d(i,j,1,n) th3d(i,j,1,n)=q ! do ktr= 1,ntracr q=tracer(i,j,k-1,n,ktr) tracer(i,j,k-1,n,ktr)=tracer(i,j,1,n,ktr) tracer(i,j, 1,n,ktr)=q enddo ! flxl(i,k-1)=0. end if enddo !k ! ! --- find buoyancy frequency for each layer ! do k=2,kk k1=k-1 k2=k+1 ! if (k.ge.kmin(i) .and. k.lt.kmax(i)) then ! --- ennsq = buoy.freq.^2 / g^2 if (locsig) then alfadt1=dsiglocdt(ahalf*(temp(i,j,k1,n)+ & temp(i,j,k ,n) ), & ahalf*(saln(i,j,k1,n)+ & saln(i,j,k, n) ),p(i,j,k))* & (temp(i,j,k1,n)- & temp(i,j,k, n) ) betads1=dsiglocds(ahalf*(temp(i,j,k1,n)+ & temp(i,j,k ,n) ), & ahalf*(saln(i,j,k1,n)+ & saln(i,j,k, n) ),p(i,j,k))* & (saln(i,j,k1,n)- & saln(i,j,k, n) ) alfadt2=dsiglocdt(ahalf*(temp(i,j,k ,n)+ & temp(i,j,k2,n) ), & ahalf*(saln(i,j,k ,n)+ & saln(i,j,k2,n) ),p(i,j,k2))* & (temp(i,j,k, n)- & temp(i,j,k2,n) ) betads2=dsiglocdt(ahalf*(temp(i,j,k ,n)+ & temp(i,j,k2,n) ), & ahalf*(saln(i,j,k ,n)+ & saln(i,j,k2,n) ),p(i,j,k2))* & (saln(i,j,k, n)- & saln(i,j,k2,n) ) ennsq=-min(0.,min(alfadt1+betads1,alfadt2+betads2)) & /max(p(i,j,k2)-p(i,j,k),onem) else ennsq=max(0.,min(th3d(i,j,k2,n)-th3d(i,j,k ,n), & th3d(i,j,k ,n)-th3d(i,j,k1,n))) & /max(p(i,j,k2)-p(i,j,k),onem) endif ! --- store (exch.coeff x buoy.freq.^2 / g x time step) in -flngth- ! ----------------------------------------------------------------------- ! --- use the following if exch.coeff. = diapyc / buoyancy frequency flngth(i,k)=(diapyc*sqrt(ennsq) * baclin*froglp * onem) ! ----------------------------------------------------------------------- ! --- use the following if exch.coeff. = diapyc !cc flngth(i,k)=diapyc*ennsq*g * baclin*froglp * onem ! ----------------------------------------------------------------------- ! end if enddo !k ! ! --- find t/s fluxes at the upper and lower interface of each layer ! --- (compute only the part common to t and s fluxes) ! do k=2,kk flxu(i,k)=0. flxl(i,k)=0. ! if (k.ge.kmin(i) .and. k.lt.kmax(i)) then ! if (locsig) then plev=p(i,j,k)+0.5*dp(i,j,k,n) alfa=-svref*dsiglocdt(temp(i,j,k,n),saln(i,j,k,n),plev) beta= svref*dsiglocds(temp(i,j,k,n),saln(i,j,k,n),plev) else alfa=-svref*dsigdt(temp(i,j,k,n),saln(i,j,k,n)) beta= svref*dsigds(temp(i,j,k,n),saln(i,j,k,n)) endif ! flxu(i,k)=flngth(i,k)/ & max(beta*(saln(i,j,k,n)-saln(i,j,k-1,n)) & -alfa*(temp(i,j,k,n)-temp(i,j,k-1,n)),small) flxl(i,k)=flngth(i,k)/ & max(beta*(saln(i,j,k+1,n)-saln(i,j,k,n)) & -alfa*(temp(i,j,k+1,n)-temp(i,j,k,n)),small) ! q=min(1.,min(p(i,j,k)-p(i,j,k-1),p(i,j,k+2)-p(i,j,k+1))/ & max(flxu(i,k),flxl(i,k),epsil)) ! !diag if (i.eq.itest .and. j.eq.jtest .and. q.ne.1.) & !diag write (lp,'(i9,2i5,i3,a,1p,2e10.2,0p,2f7.2,f4.2)') & !diag nstep,i+i0,j+j0,k,' flxu/l,dpu/l,q=',flxu(i,k),flxl(i,k), & !diag (p(i,j,k)-p(i,j,k-1))*qonem,(p(i,j,k+2)-p(i,j,k+1))*qonem,q ! flxu(i,k)=flxu(i,k)*q flxl(i,k)=flxl(i,k)*q ! end if ! kmin < k < kmax ! !diag if (i.eq.itest.and.j.eq.jtest.and.k.ge.kmin(i).and.k.le.kmax(i)) & !diag write (lp,'(i9,2i5,i3,3x,a/22x,f9.3,2f7.3,1p,3e10.3)') & !diag nstep,i+i0,j+j0,k, & !diag ' thknss temp saln flngth flxu flxl', & !diag dp(i,j,k,n)*qonem,temp(i,j,k,n),saln(i,j,k,n),flngth(i,k), & !diag flxu(i,k)*qonem,flxl(i,k)*qonem ! enddo !k ! ! --- determine mass flux -pdot- implied by t/s fluxes. ! do k=2,kk if (k.ge.kmin(i) .and. k.le.kmax(i)) & pdot(i,k)=flxu(i,k)-flxl(i,k-1) enddo !k ! ! --- convert flxu,flxl into actual salt fluxes - calculate tracer fluxes ! do k=2,kk if (k.ge.kmin(i) .and. k.lt.kmax(i)) then do ktr= 1,ntracr flxtru(i,k,ktr)=-flxu(i,k)*(tracer(i,j,k ,n,ktr)- & tracer(i,j,k-1,n,ktr)) flxtrl(i,k,ktr)=-flxl(i,k)*(tracer(i,j,k+1,n,ktr)- & tracer(i,j,k ,n,ktr)) enddo flxu(i,k)=-flxu(i,k)*(saln(i,j,k ,n)-saln(i,j,k-1,n)) flxl(i,k)=-flxl(i,k)*(saln(i,j,k+1,n)-saln(i,j,k ,n)) endif enddo !k ! ! --- update interface pressure and layer salinity do k=kk,2,-1 sold(i,2)=sold(i,1) sold(i,1)=saln(i,j,k,n) do ktr= 1,ntracr trold(i,2,ktr)=trold( i,1, ktr) trold(i,1,ktr)=tracer(i,j,k,n,ktr) enddo ! if (k.ge.kmin(i) .and. k.le.kmax(i)) then p(i,j,k)=p(i,j,k)-pdot(i,k) saln(i,j,k,n)=saln(i,j,k,n)-(flxl(i,k)-flxu(i,k)) & /max(p(i,j,k+1)-p(i,j,k),small) do ktr= 1,ntracr tracer(i,j,k,n,ktr)=tracer(i,j,k,n,ktr)- & (flxtrl(i,k,ktr)-flxtru(i,k,ktr)) & /max(p(i,j,k+1)-p(i,j,k),small) enddo ! ! --- avoid excessive salinity (and tracer) values in totally eroded layers smin=min(saln(i,j,k-1,n),sold(i,1),sold(i,2)) smax=max(saln(i,j,k-1,n),sold(i,1),sold(i,2)) saln(i,j,k,n)=max(smin,min(saln(i,j,k,n),smax)) ! do ktr= 1,ntracr trmin=min(tracer(i,j,k-1,n,ktr),trold(i,1,ktr), & trold(i,2,ktr)) trmax=max(tracer(i,j,k-1,n,ktr),trold(i,1,ktr), & trold(i,2,ktr)) tracer(i,j,k,n,ktr)=max(trmin,min(tracer(i,j,k,n,ktr),trmax)) enddo ! temp(i,j,k,n)=tofsig(th3d(i,j,k,n)+thbase,saln(i,j,k,n)) else if (kmin(i).ne.kk+1 .and. k.lt.kmin(i)) then p(i,j,k)=min(p(i,j,k),p(i,j,k+1)) end if enddo !k ! ! --- undo effect of loop 40 (i.e., restore layers 1 and kmin-1) ! do k=3,kk if (k.eq.kmin(i)) then q=temp(i,j,k-1,n) temp(i,j,k-1,n)=temp(i,j,1,n) temp(i,j,1,n)=q ! q=saln(i,j,k-1,n) saln(i,j,k-1,n)=saln(i,j,1,n) saln(i,j,1,n)=q ! q=th3d(i,j,k-1,n) th3d(i,j,k-1,n)=th3d(i,j,1,n) th3d(i,j,1,n)=q ! do ktr= 1,ntracr q=tracer(i,j,k-1,n,ktr) tracer(i,j,k-1,n,ktr)=tracer(i,j,1,n,ktr) tracer(i,j, 1,n,ktr)=q enddo endif enddo !k ! do k=kk,2,-1 ! ! --- if layer 1 has been totally eroded, transfer layer -kmin- to layer 1 if (k.eq.kmin(i) .and. p(i,j,k).lt..1*onemm) then ! !diag if (i.eq.itest .and. j.eq.jtest) then !diag write (lp,'(i9,2i5,3x,a,i3,a)') nstep,i,j,'diapfl -- layer',k, & !diag ' erodes mixed layer' !diag write (lp,'(i9,2i5,i3,3x,a/22x,f9.3,2f7.3,1p,3e10.3)') & !diag nstep,i+i0,j+j0,k, & !diag ' thknss temp saln flngth flxu flxl', & !diag (p(i,j,k+1)-p(i,j,k))*qonem,temp(i,j,k,n), & !diag saln(i,j,k,n),flngth(i,k),flxu(i,k),flxl(i,k) !diag end if ! kmin(i)=kmin(i)+1 temp(i,j,1,n)=temp(i,j,k,n) saln(i,j,1,n)=saln(i,j,k,n) th3d(i,j,1,n)=th3d(i,j,k,n) end if enddo !k ! do k=1,kk p(i,j,k+1)=max(p(i,j,k),p(i,j,k+1)) dpo(i,j,k,n)=dp(i,j,k,n) ! diapyc.flx. dp(i,j,k,n)=p(i,j,k+1)-p(i,j,k) diaflx(i,j,k)=diaflx(i,j,k)+(dp(i,j,k,n)-dpo(i,j,k,n)) ! diapyc.flx. ! --- make sure p is computed from dp, not the other way around (roundoff!) p(i,j,k+1)=p(i,j,k)+dp(i,j,k,n) enddo !k ! dpmixl(i,j,n)=dp(i,j,1,n) !diag if (i.eq.itest.and.j.eq.jtest) & !diag write (lp,'(i9,2i5,3x,a/(i36,0p,3f10.3,3p,f10.3))') & !diag nstep,i+i0,j+j0, & !diag 'after diapfl: thickness salinity temperature density', & !diag 1,dp(i,j,1,n)*qonem,saln(i,j,1,n),temp(i,j,1,n), & !diag th3d(i,j,1,n)+thbase,(k,dp(i,j,k,n)*qonem,saln(i,j,k,n), & !diag temp(i,j,k,n),th3d(i,j,k,n)+thbase,k=2,kk) ! endif !ip enddo !i ! !diag write (lp,'(i9,7x,1p,e9.2,a)') nstep,salt*1.e-6/g, & !diag ' kg salt added in diapfl' ! call dpudpv(dpu(1-nbdy,1-nbdy,1,n), & dpv(1-nbdy,1-nbdy,1,n), & p,depthu,depthv, 0,0) ! !cc write (lp,'(i9,3x,a)') nstep,'exiting d i a p f l' return end ! !> Revision history: !> !> Mar. 2000 - conversion to SI units !> May 2000 - converted T/S advection equations to flux form !> Jul. 2000 - added diapf2j for OpenMP parallelization. !> Aug. 2000 - adapted diapf3 from micom 2.8 to run within hycom 1.0 !> Jan. 2004 - added latdiw to diapf1 !> Mar. 2004 - added thkriv river support to diapf1 !> Mar. 2005 - added [ts]ofset to diapf1 and diapf2 !> Feb. 2009 - modified latdiw to use array diwlat !> Mar. 2010 - added diwbot !> Apr. 2010 - botdiw based on Decloedt&Luther in KPP&MY, removed latdiw !> Oct 2010 - replaced two calls to dsiglocdX with one call at mid-point !> Aug 2011 - replaced dpold,dpoldm with dpo !> July 2013 - added diws and diwm !> May 2014 - use land/sea masks (e.g. ip) to skip land !> July 2017 - added needed halo updates (xctilr) !> Dec. 2018 - add /* USE_NUOPC_CESMBETA */ macro and riv_input for coupled simulation