subroutine stabi #if defined O_mom && defined O_stability_tests !----------------------------------------------------------------------- ! initialization for stability testing !----------------------------------------------------------------------- implicit none include "stab.h" tdig = 1.e-4 cflcrt = 1.5 maxcfl = 3 cflons = 0.0 cflone = 360.0 cflats = -90.0 cflate = 90.0 cfldps = 0.0 cfldpe = 6000.0e2 return end subroutine stab (j, jrow) !----------------------------------------------------------------------- ! test for various measures of stability !----------------------------------------------------------------------- implicit none integer i, k, j, ip, kr, jq, jrow, is, ie, ks, ke, m, kp1, kk integer n, jj, ii, iobadt, iobads real cl, cosur, dtmax, f1, f2, f3, cflu, cflv, cflwu, cflwt real umax, pcflu, vmax, pcflv, wmax, pcflwu, pcflwt, scl, fx real dtdz, ramb, rahb, rame, ramn, rahe, rahn, reyx, reyy real reyz, pecx, pecy, pecz, tbig, tsml, tcrit, tlocal, slocal include "size.h" include "param.h" include "pconst.h" include "stdunits.h" include "accel.h" include "coord.h" include "docnam.h" include "grdvar.h" include "hmixc.h" include "iounit.h" # if defined O_isopycmix include "isopyc.h" # endif include "levind.h" include "mw.h" include "scalar.h" include "switch.h" include "stab.h" include "state.h" include "tmngr.h" include "vmixc.h" !----------------------------------------------------------------------- ! perform stability tests only within specified lat,lon and depth ! region !----------------------------------------------------------------------- if (jrow .lt. jscfl .or. jrow .gt. jecfl) return !----------------------------------------------------------------------- ! scan for CFL violations. save locations of closest approach to ! local CFL limit. !----------------------------------------------------------------------- cl = cflcrt * p5 cosur = max(csur(jrow),epsln) do k=kscfl,kecfl dtmax = max(dtuv, dtts*dtxcel(k)) f1 = dtmax*dyur(jrow) f2 = dtmax*dzwr(k) f3 = dtmax*cosur do i=iscfl,iecfl cflu = abs(f3*dxur(i)*u(i,k,j,1,tau)) cflv = abs(f1*u(i,k,j,2,tau)) cflwu = abs(f2*adv_vbu(i,k,j))*umask(i,k,j) cflwt = abs(f2*adv_vbt(i,k,j))*tmask(i,k,j) if (cflu .ge. cl .or. cflv .ge. cl .or. cflwu .ge. cl .or. & cflwt .ge. cl) then write (stdout,'(/,a33,i4,a1,i3,a1,i3,a13,f6.3,/)') & ' ==> CFL exceeded at coordinate (i,j,k) = (',i &, ',',jrow,',',k,') by factor =',cflcrt umax = p5*csu(jrow)*dxu(i)/dtmax pcflu = abs(100.0*u(i,k,j,1,tau)/umax) vmax = p5*dyu(jrow)/dtmax pcflv = abs(100.0*u(i,k,j,2,tau)/vmax) wmax = p5*dzw(k)/dtmax pcflwu= abs(100.0*adv_vbu(i,k,j)/wmax) pcflwt= abs(100.0*adv_vbt(i,k,j)/wmax) write (stdout,'(a,f8.2,a,g15.8,a)') & ' u reached ', pcflu,' % of the CFL limit (',umax,')' write (stdout,'(a,f8.2,a,g15.8,a)') & ' v reached ', pcflv,' % of the CFL limit (',vmax,')' write (stdout,'(a,f8.2,a,g15.8,a)') & ' adv_vbu reached', pcflwu,' % of the CFL limit (',wmax,')' write (stdout,'(a,f8.2,a,g15.8,a)') & ' adv_vbt reached', pcflwt,' % of the CFL limit (',wmax,')' is = max(1,i-3) ie = min(imt,i+3) ks = max(1,k-3) ke = min(km,k+3) scl = c0 fx = 1.0e-2 write (stdout,9100)'u velocity', itt &, jrow, yu(jrow), xu(is), xu(ie), fx*zt(ks), fx*zt(ke), scl call matrix (u(1,1,j,1,tau), imt, is, ie, ks, ke, scl) write (stdout,9100) 'v velocity', itt &, jrow, yu(jrow), xu(is), xu(ie), fx*zt(ks), fx*zt(ke), scl call matrix (u(1,1,j,2,tau), imt, is, ie, ks, ke, scl) write (stdout,9100) 'adv_vbu ', itt &, jrow, yu(jrow), xu(is), xu(ie), fx*zw(ks), fx*zw(ke), scl call matrix (adv_vbu(1,1,j), imt, is, ie, ks, ke, scl) write (stdout,9100) 'adv_vbt ', itt &, jrow, yt(jrow), xt(is), xt(ie), fx*zw(ks), fx*zw(ke), scl call matrix (adv_vbt(1,1,j), imt, is, ie, ks, ke, scl) do m=1,nt write (stdout,9100) trname(m), itt &, jrow, yt(jrow), xt(is), xt(ie), fx*zt(ks), fx*zt(ke), scl call matrix (t(1,1,j,m,tau), imt, is, ie, ks, ke, scl) enddo numcfl = numcfl + 1 ! turn off checking on this time step when max is exceeded if (numcfl .gt. maxcfl) stabts = .false. endif enddo enddo do k=kscfl,kecfl dtmax = max(dtuv, dtts*dtxcel(k)) vmax = p5*dyu(jrow)/dtmax wmax = p5*dzw(k)/dtmax do i=iscfl,iecfl umax = p5*csu(jrow)*dxu(i)/dtmax if (abs(100.0*u(i,k,j,1,tau)/umax) .gt. cflup) then cflup = abs(100.0*u(i,k,j,1,tau)/umax) cflum = u(i,k,j,1,tau) icflu = i jcflu = jrow kcflu = k endif if (abs(100.0*u(i,k,j,2,tau)/vmax) .gt. cflvp) then cflvp = abs(100.0*u(i,k,j,2,tau)/vmax) cflvm = u(i,k,j,2,tau) icflv = i jcflv = jrow kcflv = k endif if (abs(100.0*umask(i,k,j)*adv_vbu(i,k,j)/wmax) .gt. cflwup) & then cflwup = abs(100.0*adv_vbu(i,k,j)/wmax) cflwum = adv_vbu(i,k,j) icflwu = i jcflwu = jrow kcflwu = k endif if (abs(100.0*tmask(i,k,j)*adv_vbt(i,k,j)/wmax) .gt. cflwtp) & then cflwtp = abs(100.0*adv_vbt(i,k,j)/wmax) cflwtm = adv_vbt(i,k,j) icflwt = i jcflwt = jrow kcflwt = k endif enddo enddo !----------------------------------------------------------------------- ! look for max peclet numbers using velocities at "tau". ! look for max reynolds numbers using velocities at "tau". !----------------------------------------------------------------------- do k=kscfl,kecfl do i=iscfl,iecfl kp1 = min(k+1,km) dtdz = (t(i,k,j,1,taum1)-t(i,kp1,j,1,taum1))*dzwr(k) ramb = c1/(visc_cbu(i,k,j) + epsln) # if defined O_isopycmix rahb = dtdz/(diff_fbiso(i,k,j) + diff_fb(i,k,j) + epsln) # else rahb = dtdz/(diff_cbt(i,k,j)*dtdz + epsln) # endif # if defined O_consthmix rame = c1/(visc_ceu + epsln) ramn = c1/(visc_cnu + epsln) # if defined O_isopycmix rahe = c1/(ah+ahisop*fisop(i,jrow,k)) rahn = c1/(ah+ahisop*fisop(i,jrow,k)) # else # if defined O_bryan_lewis_horizontal rahe = c1/(diff_cet(k) + epsln) rahn = c1/(diff_cnt(k) + epsln) # else rahe = c1/(diff_cet + epsln) rahn = c1/(diff_cnt + epsln) # endif # endif # else rame = c1/(visc_ceu(i,k,j) + epsln) ramn = c1/(visc_cnu(i,k,j) + epsln) rahe = c1/(diff_cet(i,k,j) + epsln) rahn = c1/(diff_cnt(i,k,j) + epsln) # endif reyx = abs(u(i,k,j,1,tau)*dxu(i))*rame if (reyx .gt. reynx) then ireynx = i jreynx = jrow kreynx = k reynx = reyx reynu = u(i,k,j,1,tau) reynmu = c1/rame endif reyy = abs(u(i,k,j,2,tau)*dyu(jrow))*ramn if (reyy .gt. reyny) then ireyny = i jreyny = jrow kreyny = k reyny = reyy reynv = u(i,k,j,2,tau) reynmv = c1/ramn endif kk = min(k+1,km) if (k .ge. kmu(i,jrow)) then reyz = c0 else reyz =umask(i,kk,j)*abs(adv_vbu(i,k,j)*dzw(k))*ramb endif if (reyz .gt. reynz) then ireynz = i jreynz = jrow kreynz = k reynz = reyz reynw = adv_vbu(i,k,j) reynmw = c1/ramb endif pecx = abs(u(i,k,j,1,tau)*dxu(i))*rahe if (pecx .gt. peclx) then ipeclx = i jpeclx = jrow kpeclx = k peclx = pecx peclu = u(i,k,j,1,tau) peclmu = c1/rahe endif pecy = abs(u(i,k,j,2,tau)*dyu(jrow))*rahn if (pecy .gt. pecly) then ipecly = i jpecly = jrow kpecly = k pecly = pecy peclv = u(i,k,j,2,tau) peclmv = c1/rahn endif kk = min(k+1,km) if (k .ge. kmt(i,jrow)) then pecz = 0.0 else pecz =tmask(i,kk,j)*abs(adv_vbt(i,k,j)*dzw(k))*rahb endif if (pecz .gt. peclz) then ipeclz = i jpeclz = jrow kpeclz = k peclz = pecz peclw = adv_vbt(i,k,j) peclmw = c1/rahb endif enddo enddo !----------------------------------------------------------------------- ! look for ficticious creation of local extremum for tracers ! by finding local min and max tracer at "tau" and comparing to ! tracer at "tau+1" !----------------------------------------------------------------------- call getunit (iostab, 'iostab' &, 'formatted sequential append') ks = max(2,kscfl) ke = min(km-1,kecfl) is = max(2,iscfl) ie = min(imt-1,iecfl) do n=1,nt do k=ks,ke do i=is,ie if (tmask(i,k,j) .ne. c0) then tbig = max(t(i,k,j,n,tau),t(i,k,j,n,taum1)) tsml = min(t(i,k,j,n,tau),t(i,k,j,n,taum1)) do jj=j-1,j+1,2 if (tmask(i,k,jj) .ne. c0) then tbig = max(tbig,t(i,k,jj,n,tau),t(i,k,jj,n,taum1)) tsml = min(tsml,t(i,k,jj,n,tau),t(i,k,jj,n,taum1)) endif enddo do ii=i-1,i+1,2 if (tmask(ii,k,j) .ne. c0) then tbig = max(tbig,t(ii,k,j,n,tau),t(ii,k,j,n,taum1)) tsml = min(tsml,t(ii,k,j,n,tau),t(ii,k,j,n,taum1)) endif enddo do kk=k-1,k+1,2 if (tmask(i,kk,j) .ne. c0) then tbig = max(tbig,t(i,kk,j,n,tau),t(i,kk,j,n,taum1)) tsml = min(tsml,t(i,kk,j,n,tau),t(i,kk,j,n,taum1)) endif enddo tcrit = tdig*abs(t(i,k,j,n,taup1)) if (tmask(i,k,j) .ne. c0 .and. & ((t(i,k,j,n,taup1) .gt. tbig + tcrit) & .or. (t(i,k,j,n,taup1) .lt. tsml - tcrit))) then write (iostab,'(i4, i4, i4, i2, 3g14.7)') & i, k, jrow, n, t(i,k,j,n,taup1), tsml, tbig endif endif enddo enddo enddo call relunit (iostab) !----------------------------------------------------------------------- ! look for temperatures and salinities outside ranges used for ! specifying density coefficients !----------------------------------------------------------------------- call getunit (iobadt, 'iobadt' &, 'formatted sequential append') call getunit (iobads, 'iobads' &, 'formatted sequential append') ks = max(1,kscfl) ke = min(km,kecfl) is = max(2,iscfl) ie = min(imt-1,iecfl) do k=1,km do i=is,ie if (tmask(i,k,j) .ne. c0) then tlocal = t(i,k,j,1,taup1) slocal = t(i,k,j,2,taup1)*1000.0 + 35.0 n = 1 if (tlocal .lt. tmink(k) .or. tlocal .gt. tmaxk(k)) then write (iobadt,'(i4, i4, i4, i2, 3g14.7)') & i, k, jrow, n, tlocal, tmink(k), tmaxk(k) endif n = 2 if (slocal .lt. smink(k) .or. slocal .gt. smaxk(k)) then write (iobads,'(i4, i4, i4, i2, 3g14.7)') & i, k, jrow, n, slocal, smink(k), smaxk(k) endif endif enddo enddo call relunit (iobadt) call relunit (iobads) 9100 format(1x,a12,1x,'ts=',i10,1x,',j=',i3,', lat=',f6.2 &,', lon:',f6.2,' ==> ',f6.2,', depth(m):',f6.1,' ==> ',f6.1 &,', scaling=',1pg10.3) #endif return end