Blame | Last modification | View Log | Download | RSS feed
PROGRAM z2sc Calculate secondary fields on z levelsc Michael Sprenger / Summer 2006implicit nonec ---------------------------------------------------------------c Declaration of parametersc ---------------------------------------------------------------real tzeroparameter (tzero=273.15)real kappaparameter (kappa=0.6078)real rdparameter (rd=287.)c ---------------------------------------------------------------c Declaration of variablesc ---------------------------------------------------------------c Variables for output Z file : height levelcharacter*80 cfnreal varmin(4),varmax(4),stag(4)integer vardim(4)real mdvinteger ndiminteger nx,ny,nzreal xmin,xmax,ymin,ymax,dx,dyinteger ntimesreal aklev(1000),bklev(1000)real aklay(1000),bklay(1000)real timereal pollon,pollatinteger idate(5)integer nfieldscharacter*80 field_nam(100)real,allocatable, dimension (:,:,:,:) :: field_datreal,allocatable, dimension (:,:,:) :: z3real,allocatable, dimension (:,:) :: x2,y2,f2,ororeal,allocatable, dimension (:,:,:) :: out1,out2real,allocatable, dimension (:,:,:) :: inpreal,allocatable,dimension (:) :: nsqrefreal,allocatable,dimension (:) :: thetarefreal,allocatable,dimension (:) :: trefreal,allocatable,dimension (:) :: rhorefreal,allocatable,dimension (:) :: pressrefreal,allocatable,dimension (:) :: zrefreal deltax,deltay,deltazinteger nvarscharacter*80 vnam(100),varnameinteger isokinteger cdfid,cstidcharacter*3 modec Parameter filecharacter*80 fieldnameinteger nfiltcharacter*80 ofn,gric Auxiliary variablesinteger ierr,statinteger i,j,k,nreal,allocatable, dimension (:,:) :: tmpcharacter*80 vnam2(100)integer nvars2c ---------------------------------------------------------------c Preparationsc ---------------------------------------------------------------print*,'*********************************************************'print*,'* qvec_analysis *'print*,'*********************************************************'c Read parameter fileopen(10,file='fort.10')read(10,*) fieldnameread(10,*) ofnread(10,*) griread(10,*) nfiltclose(10)c Decide whether to enter ANO or MOD/ORG modemode = ofn(1:3)if ( (mode.ne.'ANO').and.> (mode.ne.'MOD').and.> (mode.ne.'ORG') )>thenprint*,'Unsupported mode ',trim(mode)stopendifc Get grid description for Z file : height levelcall cdfopn(ofn,cdfid,ierr)if (ierr.ne.0) goto 998call getcfn(cdfid,cfn,ierr)if (ierr.ne.0) goto 998call cdfopn(cfn,cstid,ierr)if (ierr.ne.0) goto 998call getdef(cdfid,'T',ndim,mdv,vardim,> varmin,varmax,stag,ierr)if (ierr.ne.0) goto 998nx =vardim(1)ny =vardim(2)nz =vardim(3)xmin=varmin(1)ymin=varmin(2)call getlevs(cstid,nz,aklev,bklev,aklay,bklay,ierr)if (ierr.ne.0) goto 998call getgrid(cstid,dx,dy,ierr)if (ierr.ne.0) goto 998xmax=xmin+real(nx-1)*dxymax=ymin+real(ny-1)*dycall gettimes(cdfid,time,ntimes,ierr)if (ierr.ne.0) goto 998call getstart(cstid,idate,ierr)if (ierr.ne.0) goto 998call getpole(cstid,pollon,pollat,ierr)if (ierr.ne.0) goto 998call getvars(cdfid,nvars,vnam,ierr)if (ierr.ne.0) goto 998call clscdf(cstid,ierr)if (ierr.ne.0) goto 998call clscdf(cdfid,ierr)if (ierr.ne.0) goto 998c Get a list of all variables on the GRID fileif (trim(gri).ne.trim(ofn)) thencall cdfopn(gri,cdfid,ierr)if (ierr.ne.0) goto 998call getvars(cdfid,nvars2,vnam2,ierr)if (ierr.ne.0) goto 998do i=1,nvars2vnam(nvars+i)=vnam2(i)enddonvars=nvars+nvars2endifc Check whether calculation of <fieldname> is supportedif ( (fieldname.ne.'GEO' ).and.> (fieldname.ne.'AGEO' ).and.> (fieldname.ne.'DIV_UV' ).and.> (fieldname.ne.'QVEC' ).and.> (fieldname.ne.'DIV_Q' ) ) thenprint*,'Variable not supported ',trim(fieldname)stopendifc Set dependenciesif (fieldname.eq.'GEO') thennfields=2field_nam(1)='T'field_nam(2)='P'elseif (fieldname.eq.'AGEO') thennfields=4field_nam(1)='U'field_nam(2)='UG'field_nam(3)='V'field_nam(4)='VG'else if (fieldname.eq.'DIV_UV') thennfields=2field_nam(1)='U'field_nam(2)='V'else if (fieldname.eq.'QVEC') thennfields=3field_nam(1)='UG'field_nam(2)='VG'field_nam(3)='TH'else if (fieldname.eq.'DIV_Q') thennfields=2field_nam(1)='QX'field_nam(2)='QY'endifc Allocate memoryallocate(field_dat(nfields,nx,ny,nz),stat=stat)if (stat.ne.0) print*,'error allocating field_dat'allocate(out1(nx,ny,nz),stat=stat)if (stat.ne.0) print*,'error allocating out1'allocate(out2(nx,ny,nz),stat=stat)if (stat.ne.0) print*,'error allocating out2'allocate(inp(nx,ny,nz),stat=stat)if (stat.ne.0) print*,'error allocating inp'allocate(z3(nx,ny,nz),stat=stat)if (stat.ne.0) print*,'error allocating z3'allocate(x2(nx,ny),stat=stat)if (stat.ne.0) print*,'error allocating x2'allocate(y2(nx,ny),stat=stat)if (stat.ne.0) print*,'error allocating y2'allocate(f2(nx,ny),stat=stat)if (stat.ne.0) print*,'error allocating f2'allocate(oro(nx,ny),stat=stat)if (stat.ne.0) print*,'error allocating oro'C Allocate memory for reference profileallocate(rhoref (0:2*nz),STAT=stat)if (stat.ne.0) print*,'error allocating rhoref'allocate(pressref(0:2*nz),STAT=stat)if (stat.ne.0) print*,'error allocating pressref'allocate(thetaref(0:2*nz),STAT=stat)if (stat.ne.0) print*,'error allocating thetaref'allocate(nsqref (0:2*nz),STAT=stat)if (stat.ne.0) print*,'error allocating nsqref'allocate(zref (0:2*nz),STAT=stat)if (stat.ne.0) print*,'error allocating zref'allocate(tref (0:2*nz),STAT=stat)if (stat.ne.0) print*,'error allocating tref'c Allocate auxiliary fieldsallocate(tmp(nx,ny),stat=stat)if (stat.ne.0) print*,'error allocating tmp'c Read reference profile and grid parameterscall read_ref (nsqref,rhoref,thetaref,pressref,zref,> nx,ny,nz,deltax,deltay,deltaz,f2,oro,gri)c Read X gridvarname='X'isok=0call check_varok (isok,varname,vnam,nvars)if (isok.eq.0) thenprint*,'Variable ',trim(varname),' missing... Stop'stopendifcall cdfopn(gri,cdfid,ierr)if (ierr.ne.0) goto 998call getdat(cdfid,varname,time,0,x2,ierr)if (ierr.ne.0) goto 998print*,'R ',trim(varname),' ',trim(gri)call clscdf(cdfid,ierr)if (ierr.ne.0) goto 998c Read Y gridvarname='Y'isok=0call check_varok (isok,varname,vnam,nvars)if (isok.eq.0) thenprint*,'Variable ',trim(varname),' missing... Stop'stopendifcall cdfopn(gri,cdfid,ierr)if (ierr.ne.0) goto 998call getdat(cdfid,varname,time,0,y2,ierr)if (ierr.ne.0) goto 998print*,'R ',trim(varname),' ',trim(gri)call clscdf(cdfid,ierr)if (ierr.ne.0) goto 998c Calculate reference profile of temperatureprint*,'C T_ref = TH_ref * ( P_ref/1000)^kappa'do i=0,2*nztref(i) = thetaref(i) * ( pressref(i)/1000. ) ** kappaenddoc Init height levelsdo i=1,nxdo j=1,nydo k=1,nzz3(i,j,k)=zref(2*k-1)enddoenddoenddoc Load needed variablesdo n=1,nfieldsc Check whether variable is available on filevarname=field_nam(n)isok=0call check_varok (isok,varname,vnam,nvars)c Variable is available on fileif (isok.eq.1) thencall cdfopn(ofn,cdfid,ierr)if (ierr.ne.0) goto 998call getdat(cdfid,varname,time,0,inp,ierr)if (ierr.ne.0) goto 998print*,'R ',trim(varname),' ',trim(ofn)call clscdf(cdfid,ierr)if (ierr.ne.0) goto 998do i=1,nxdo j=1,nydo k=1,nzfield_dat(n,i,j,k)=inp(i,j,k)enddoenddoenddoelseprint*,'Variable missing : ',trim(varname)stopendifenddoc Add reference profile if ANO file is providedif ( mode.eq.'ANO' ) thenprint*,'C T -> T_ano + T_ref'n=0do i=1,nfieldsif (field_nam(i).eq.'T') n=ienddoif (n.ne.0) thendo i=1,nxdo j=1,nydo k=1,nzfield_dat(n,i,j,k) = field_dat(n,i,j,k) + tref(2*k-1)enddoenddoenddoendifprint*,'C TH -> TH_ano + TH_ref'n=0do i=1,nfieldsif (field_nam(i).eq.'TH') n=ienddoif (n.ne.0) thendo i=1,nxdo j=1,nydo k=1,nzfield_dat(n,i,j,k) = field_dat(n,i,j,k)+thetaref(2*k-1)enddoenddoenddoendifprint*,'C P -> P_ano + P_ref'n=0do i=1,nfieldsif (field_nam(i).eq.'P') n=ienddoif (n.ne.0) thendo i=1,nxdo j=1,nydo k=1,nzfield_dat(n,i,j,k) = field_dat(n,i,j,k)+pressref(2*k-1)enddoenddoenddoendifendifc Change units: P (hPa -> Pa), T(K -> degC)n=0do i=1,nfieldsif (field_nam(i).eq.'P') n=ienddoif (n.ne.0) thendo i=1,nxdo j=1,nydo k=1,nzfield_dat(n,i,j,k)=100.*field_dat(n,i,j,k)enddoenddoenddoendifn=0do i=1,nfieldsif (field_nam(i).eq.'T') n=ienddoif (n.ne.0) thendo i=1,nxdo j=1,nydo k=1,nzif ( field_dat(n,i,j,1).gt.100. ) thenfield_dat(n,i,j,k)=field_dat(n,i,j,k) - tzeroendifenddoenddoenddoendifc ----------------------------------------------------------------c Calculationsc ----------------------------------------------------------------c Geostrophic wind (GEO)if (fieldname.eq.'GEO') thenprint*,'C ',trim(fieldname)field_nam(1)='RHO'do i=1,nxdo j=1,nydo k=1,nzif ( mode.eq.'ANO' ) thenfield_dat(1,i,j,k)=rhoref(2*k-1)elsefield_dat(1,i,j,k)=> 1./rd*field_dat(2,i,j,k)/(field_dat(1,i,j,k)+tzero)endifenddoenddoenddocall calc_geo (out1,out2, ! (Ug,Vg)> field_dat(1,:,:,:), ! RHO> field_dat(2,:,:,:), ! P> z3,x2,y2,f2, ! Z,X,Y,CORIOL> nx,ny,nz,mdv)c Ageostrophic wind (AGEO)elseif (fieldname.eq.'AGEO') thenprint*,'C ',trim(fieldname)call calc_ageo (out1,out2, ! (Ua,Va)> field_dat(1,:,:,:), ! U> field_dat(2,:,:,:), ! UG> field_dat(3,:,:,:), ! V> field_dat(4,:,:,:), ! VG> nx,ny,nz,mdv)c Divergence of wind (DIV_UV)else if (fieldname.eq.'DIV_UV') thenprint*,'C ',trim(fieldname)call calc_div_uv (out1, ! Div(U,V))> field_dat(1,:,:,:), ! U> field_dat(2,:,:,:), ! V> z3,x2,y2,f2, ! Z,X,Y,CORIOL> nx,ny,nz,mdv)c Q vector (QVEC)else if (fieldname.eq.'QVEC') thenprint*,'C ',trim(fieldname)call calc_qvec (out1,out2, ! (Qx,Qy)> field_dat(1,:,:,:), ! UG> field_dat(2,:,:,:), ! VG> field_dat(3,:,:,:), ! TH> z3,x2,y2,f2, ! Z,X,Y,CORIOL> nx,ny,nz,mdv)c Divergence of Q vector (DIV_Q)else if (fieldname.eq.'DIV_Q') thenprint*,'C ',trim(fieldname)call calc_div_q (out1, ! Div(U,V))> field_dat(1,:,:,:), ! QX> field_dat(2,:,:,:), ! QY> z3,x2,y2,f2, ! Z,X,Y,CORIOL> nx,ny,nz,mdv)endifc Horizontal filtering of the resulting fieldsprint*,'F ',trim(fieldname)do k=1,nzdo i=1,nxdo j=1,nytmp(i,j)=out1(i,j,k)enddoenddodo n=1,nfiltcall filt2d (tmp,tmp,nx,ny,1.,mdv,0,0,0,0)enddodo i=1,nxdo j=1,nyout1(i,j,k)=tmp(i,j)enddoenddodo i=1,nxdo j=1,nytmp(i,j)=out2(i,j,k)enddoenddodo n=1,nfiltcall filt2d (tmp,tmp,nx,ny,1.,mdv,0,0,0,0)enddodo i=1,nxdo j=1,nyout2(i,j,k)=tmp(i,j)enddoenddoenddoc ----------------------------------------------------------------c Save result onto netcdf filec ----------------------------------------------------------------c Open output filecall cdfwopn(ofn,cdfid,ierr)if (ierr.ne.0) goto 998c Save geostrophic windif (fieldname.eq.'GEO') thenisok=0varname='UG'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndim,mdv,vardim,> varmin,varmax,stag,ierr)if (ierr.ne.0) goto 998endifcall putdat(cdfid,varname,time,0,out1,ierr)if (ierr.ne.0) goto 998print*,'W ',trim(varname),' ',trim(ofn)isok=0varname='VG'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndim,mdv,vardim,> varmin,varmax,stag,ierr)if (ierr.ne.0) goto 998endifcall putdat(cdfid,varname,time,0,out2,ierr)if (ierr.ne.0) goto 998print*,'W ',trim(varname),' ',trim(ofn)c Save ageostrophic windelseif (fieldname.eq.'AGEO') thenisok=0varname='UA'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndim,mdv,vardim,> varmin,varmax,stag,ierr)if (ierr.ne.0) goto 998endifcall putdat(cdfid,varname,time,0,out1,ierr)if (ierr.ne.0) goto 998print*,'W ',trim(varname),' ',trim(ofn)isok=0varname='VA'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndim,mdv,vardim,> varmin,varmax,stag,ierr)if (ierr.ne.0) goto 998endifcall putdat(cdfid,varname,time,0,out2,ierr)if (ierr.ne.0) goto 998print*,'W ',trim(varname),' ',trim(ofn)c Save divergence of wind fieldelse if (fieldname.eq.'DIV_UV') thenisok=0varname='DIV_UV'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndim,mdv,vardim,> varmin,varmax,stag,ierr)if (ierr.ne.0) goto 998endifcall putdat(cdfid,varname,time,0,out1,ierr)if (ierr.ne.0) goto 998print*,'W ',trim(varname),' ',trim(ofn)c Save components of Q vectorelse if (fieldname.eq.'QVEC') thenisok=0varname='QX'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndim,mdv,vardim,> varmin,varmax,stag,ierr)if (ierr.ne.0) goto 998endifcall putdat(cdfid,varname,time,0,out1,ierr)if (ierr.ne.0) goto 998print*,'W ',trim(varname),' ',trim(ofn)isok=0varname='QY'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndim,mdv,vardim,> varmin,varmax,stag,ierr)if (ierr.ne.0) goto 998endifcall putdat(cdfid,varname,time,0,out2,ierr)if (ierr.ne.0) goto 998print*,'W ',trim(varname),' ',trim(ofn)c Save divergence of wind fieldelse if (fieldname.eq.'DIV_Q') thenisok=0varname='DIV_Q'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndim,mdv,vardim,> varmin,varmax,stag,ierr)if (ierr.ne.0) goto 998endifcall putdat(cdfid,varname,time,0,out1,ierr)if (ierr.ne.0) goto 998print*,'W ',trim(varname),' ',trim(ofn)endifc Close output filecall clscdf(cdfid,ierr)if (ierr.ne.0) goto 998c ----------------------------------------------------------------c Exception handlingc ----------------------------------------------------------------stop998 print*,'Problem with netcdf file'stopendc ****************************************************************c * SUBROUTINE SECTION: AUXILIARY ROUTINES *c ****************************************************************c ----------------------------------------------------------------c Check whether variable is found on netcdf filec ----------------------------------------------------------------subroutine check_varok (isok,varname,varlist,nvars)c Check whether the variable <varname> is in the list <varlist(nvars)>.c If this is the case, <isok> is incremented by 1. Otherwise <isok>c keeps its value.implicit nonec Declaraion of subroutine parametersinteger isokinteger nvarscharacter*80 varnamecharacter*80 varlist(nvars)c Auxiliary variablesinteger ic Maindo i=1,nvarsif (trim(varname).eq.trim(varlist(i))) isok=isok+1enddoendc ****************************************************************c * SUBROUTINE SECTION: CALCULATE SECONDARY FIELDS *c ****************************************************************c ----------------------------------------------------------------c Calculate geostrophic wind componentsc ----------------------------------------------------------------subroutine calc_geo (ug,vg,rho,p,> z3,x2,y2,f2,nx,ny,nz,mdv)c Calculate the geostrophic wind components (ug,vg) if the temperaturec (t) and the pressure (p) are given. The grid and the missing datac value are specified by (z3,x2,y2,f2,nx,ny,nz,mdv)implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal ug (nx,ny,nz)real vg (nx,ny,nz)real rho(nx,ny,nz)real p (nx,ny,nz)real z3 (nx,ny,nz)real x2 (nx,ny)real y2 (nx,ny)real f2 (nx,ny)real mdvc Physical parameters and numerical constantsreal epsparameter (eps=0.01)real gparameter (g=9.80616)c Auxiliray variablesinteger i,j,kreal dpdx(nx,ny,nz)real dpdy(nx,ny,nz)c Calculate horizontal derivatives of pressurecall deriv(dpdx,p,'x',z3,x2,y2,nx,ny,nz,mdv)call deriv(dpdy,p,'y',z3,x2,y2,nx,ny,nz,mdv)c Calculationdo i=1,nxdo j=1,nydo k=1,nzif ((abs(rho (i,j,k)-mdv).gt.eps).and.> (abs(dpdx(i,j,k)-mdv).gt.eps).and.> (abs(dpdy(i,j,k)-mdv).gt.eps)) thenug(i,j,k)=-1./(rho(i,j,k)*f2(i,j))*dpdy(i,j,k)vg(i,j,k)= 1./(rho(i,j,k)*f2(i,j))*dpdx(i,j,k)endifenddoenddoenddoendc ----------------------------------------------------------------c Calculate ageostrophic wind componentsc ----------------------------------------------------------------subroutine calc_ageo (ua,va,u,ug,v,vg,nx,ny,nz,mdv)c Calculate the geostrophic wind components (ug,vg) if the temperaturec (t) and the pressure (p) are given. The grid and the missing datac value are specified by (z3,x2,y2,f2,nx,ny,nz,mdv)implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal ua (nx,ny,nz)real va (nx,ny,nz)real u (nx,ny,nz)real ug (nx,ny,nz)real v (nx,ny,nz)real vg (nx,ny,nz)real mdvc Parametersreal epsparameter (eps=0.01)c Auxiliray variablesinteger i,j,kc Calculationdo i=1,nxdo j=1,nydo k=1,nzif ((abs(u (i,j,k)-mdv).gt.eps).and.> (abs(ug(i,j,k)-mdv).gt.eps).and.> (abs(v (i,j,k)-mdv).gt.eps).and.> (abs(vg(i,j,k)-mdv).gt.eps)) thenua(i,j,k)=u(i,j,k) - ug(i,j,k)va(i,j,k)=v(i,j,k) - vg(i,j,k)endifenddoenddoenddoendc ----------------------------------------------------------------c Calculate divergence of wind fieldc ----------------------------------------------------------------subroutine calc_div_uv (div_uv,u,v,> z3,x2,y2,f2,nx,ny,nz,mdv)c Calculate the divergence (div_uv) of the horizontal wind field if+c the wind components (u,v) are given. The grid and the missing datac value are specified by (z3,x2,y2,f2,nx,ny,nz,mdv)implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal div_uv(nx,ny,nz)real u (nx,ny,nz)real v (nx,ny,nz)real z3 (nx,ny,nz)real x2 (nx,ny)real y2 (nx,ny)real f2 (nx,ny)real mdvc Physical parameters and numerical constantsreal epsparameter (eps=0.01)c Auxiliray variablesinteger i,j,kreal rhoreal dudx(nx,ny,nz)real dvdy(nx,ny,nz)c Calculate horizontal derivatives of pressurecall deriv(dudx,u,'x',z3,x2,y2,nx,ny,nz,mdv)call deriv(dvdy,v,'y',z3,x2,y2,nx,ny,nz,mdv)c Calculationdo i=1,nxdo j=1,nydo k=1,nzif ((abs(dudx(i,j,k)-mdv).gt.eps).and.> (abs(dvdy(i,j,k)-mdv).gt.eps)) thendiv_uv(i,j,k)=dudx(i,j,k)+dvdy(i,j,k)endifenddoenddoenddoendc ----------------------------------------------------------------c Calculate Q vectorc ----------------------------------------------------------------subroutine calc_qvec (qx3,qy3,> th3,u3,v3,> z3,x2,y2,f2,nx,ny,nz,mdv)c Calculate teh Q vector components <qx3> and <qy3>, as well as the divergencec of the Q vector <divq3> on the model grid. The grid is specified in the horizontalc by <xmin,ymin,dx,dy,nx,ny>. The number of vertical levels is <nz>. The input fieldc are: potential temperature <th3>, horizontal wind <u3> and <v3>, pressure <p3>.c The calculation follows the one described in "Weather Analysis, Dusan Djuric"implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal qx3(nx,ny,nz)real qy3(nx,ny,nz)real th3(nx,ny,nz)real u3 (nx,ny,nz)real v3 (nx,ny,nz)real z3 (nx,ny,nz)real x2 (nx,ny)real y2 (nx,ny)real f2 (nx,ny)real mdvc Physical and numerical parametersreal scale1,scale2parameter (scale1=1.E10,scale2=1.E14)real epsparameter (eps=0.01)real gparameter (g=9.80616)real tzeroparameter (tzero=273.16)c Auxiliary variablesreal dudx(nx,ny,nz)real dudy(nx,ny,nz)real dvdx(nx,ny,nz)real dvdy(nx,ny,nz)real dtdx(nx,ny,nz)real dtdy(nx,ny,nz)integer i,j,kc Needed derivativescall deriv (dudx, u3,'x',z3,x2,y2,nx,ny,nz,mdv)call deriv (dudy, u3,'y',z3,x2,y2,nx,ny,nz,mdv)call deriv (dvdx, v3,'x',z3,x2,y2,nx,ny,nz,mdv)call deriv (dvdy, v3,'y',z3,x2,y2,nx,ny,nz,mdv)call deriv (dtdx,th3,'x',z3,x2,y2,nx,ny,nz,mdv)call deriv (dtdy,th3,'y',z3,x2,y2,nx,ny,nz,mdv)c Calculate vector components of the Q vectordo i=1,nxdo j=1,nydo k=1,nzc Evaluate Q vector formula with missing data checkif ((abs(dudx(i,j,k)-mdv).gt.eps).and.> (abs(dudy(i,j,k)-mdv).gt.eps).and.> (abs(dvdx(i,j,k)-mdv).gt.eps).and.> (abs(dvdy(i,j,k)-mdv).gt.eps).and.> (abs(dtdx(i,j,k)-mdv).gt.eps).and.> (abs(dtdy(i,j,k)-mdv).gt.eps)) thenqx3(i,j,k) = -g/tzero * (dudx(i,j,k)*dtdx(i,j,k)> +dvdx(i,j,k)*dtdy(i,j,k))qy3(i,j,k) = -g/tzero * (dudy(i,j,k)*dtdx(i,j,k)> +dvdy(i,j,k)*dtdy(i,j,k))elseqx3(i,j,k)=mdvqy3(i,j,k)=mdvendifenddoenddoenddoc Scale the outputdo i=1,nxdo j=1,nydo k=1,nzif (abs(qx3(i,j,k)-mdv).gt.eps) thenqx3(i,j,k)=scale1*qx3(i,j,k)endifif (abs(qy3(i,j,k)-mdv).gt.eps) thenqy3(i,j,k)=scale1*qy3(i,j,k)endifenddoenddoenddoendc ----------------------------------------------------------------c Calculate divergence of wind fieldc ----------------------------------------------------------------subroutine calc_div_q (div_q,qx,qy,> z3,x2,y2,f2,nx,ny,nz,mdv)c Calculate the divergence (div_q) of the Q vector field ifc the components (qx,qy) are given. The grid and the missing datac value are specified by (z3,x2,y2,f2,nx,ny,nz,mdv)implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal div_q(nx,ny,nz)real qx (nx,ny,nz)real qy (nx,ny,nz)real z3 (nx,ny,nz)real x2 (nx,ny)real y2 (nx,ny)real f2 (nx,ny)real mdvc Physical parameters and numerical constantsreal epsparameter (eps=0.01)c Auxiliray variablesinteger i,j,kreal rhoreal dqxdx(nx,ny,nz)real dqydy(nx,ny,nz)c Calculate horizontal derivatives of pressurecall deriv(dqxdx,qx,'x',z3,x2,y2,nx,ny,nz,mdv)call deriv(dqydy,qy,'y',z3,x2,y2,nx,ny,nz,mdv)c Calculationdo i=1,nxdo j=1,nydo k=1,nzif ((abs(dqxdx(i,j,k)-mdv).gt.eps).and.> (abs(dqydy(i,j,k)-mdv).gt.eps)) thendiv_q(i,j,k)=dqxdx(i,j,k)+dqydy(i,j,k)endifenddoenddoenddoendc ****************************************************************c * SUBROUTINE SECTION: GRID HANDLING *c ****************************************************************c -----------------------------------------------------------------c Horizontal and vertical derivatives for 3d fieldsc -----------------------------------------------------------------subroutine deriv (df,f,direction,> z3,x2,y2,nx,ny,nz,mdv)c Calculate horizontal and vertical derivatives of the 3d field <f>.c The direction of the derivative is specified in <direction>c 'x','y' : Horizontal derivative in x and y directionc 'p','z','t','m' : Vertical derivative (pressure, height, theta, model)c The 3d field <z3> specifies the isosurfaces along which the horizontalc derivatives are calculated or the levels for the vertical derivatives.implicit nonec Input and output parametersinteger nx,ny,nzreal df (nx,ny,nz)real f (nx,ny,nz)real z3 (nx,ny,nz)real x2 (nx,ny)real y2 (nx,ny)character directionreal mdvc Numerical and physical parametersreal pi180parameter (pi180=3.141592654/180.)real deltayparameter (deltay=111.1775E3)real zerodivparameter (zerodiv=0.00000001)real epsparameter (eps=0.01)c Auxiliary variablesinteger i,j,kreal vmin,vmaxreal scale,latreal vu,vl,vuvl,vlvuinteger o,u,w,e,n,sc Vertical derivativeif ((direction.eq.'z').or.> (direction.eq.'th').or.> (direction.eq.'p').or.> (direction.eq.'m').and.> (nz.gt.1)) thendo i=1,nxdo j=1,nydo k=1,nzo=k+1if (o.gt.nz) o=nzu=k-1if (u.lt.1) u=1if ((abs(f(i,j,o)-mdv).gt.eps).and.> (abs(f(i,j,u)-mdv).gt.eps).and.> (abs(f(i,j,k)-mdv).gt.eps)) thenvu = z3(i,j,k)-z3(i,j,o)vl = z3(i,j,u)-z3(i,j,k)vuvl = vu/(vl+zerodiv)vlvu = 1./(vuvl+zerodiv)df(i,j,k) = 1./(vu+vl)> * (vuvl*(f(i,j,u)-f(i,j,k))> + vlvu*(f(i,j,k)-f(i,j,o)))elsedf(i,j,k) = mdvendifenddoenddoenddoc Horizontal derivative in the y direction: 3delseif (direction.eq.'y') thendo i=1,nxdo j=1,nydo k=1,nzs=j-1if (s.lt.1) s=1n=j+1if (n.gt.ny) n=nyif ((abs(f(i,n,k)-mdv).gt.eps).and.> (abs(f(i,j,k)-mdv).gt.eps).and.> (abs(f(i,s,k)-mdv).gt.eps)) thenvu = 1000.*(y2(i,j)-y2(i,n))vl = 1000.*(y2(i,s)-y2(i,j))vuvl = vu/(vl+zerodiv)vlvu = 1./(vuvl+zerodiv)df(i,j,k) = 1./(vu+vl)> * (vuvl*(f(i,s,k)-f(i,j,k))> + vlvu*(f(i,j,k)-f(i,n,k)))elsedf(i,j,k) = mdvendifenddoenddoenddoc Horizontal derivative in the x direction: 3delseif (direction.eq.'x') thendo i=1,nxdo j=1,nydo k=1,nzw=i-1if (w.lt.1) w=1e=i+1if (e.gt.nx) e=nxif ((abs(f(w,j,k)-mdv).gt.eps).and.> (abs(f(i,j,k)-mdv).gt.eps).and.> (abs(f(e,j,k)-mdv).gt.eps)) thenvu = 1000.*(x2(i,j)-x2(e,j))vl = 1000.*(x2(w,j)-x2(i,j))vuvl = vu/(vl+zerodiv)vlvu = 1./(vuvl+zerodiv)df(i,j,k) = 1./(vu+vl)> * (vuvl*(f(w,j,k)-f(i,j,k))> + vlvu*(f(i,j,k)-f(e,j,k)))elsedf(i,j,k) = mdvendifenddoenddoenddoc Undefined direction for derivativeelseprint*,'Invalid direction of derivative... Stop'stopendifendc -----------------------------------------------------------------c Horizontal filterc -----------------------------------------------------------------subroutine filt2d (a,af,nx,ny,fil,misdat,& iperx,ipery,ispol,inpol)c Apply a conservative diffusion operator onto the 2d field a,c with full missing data checking.cc a real inp array to be filtered, dimensioned (nx,ny)c af real out filtered array, dimensioned (nx,ny), can bec equivalenced with array a in the calling routinec f1 real workarray, dimensioned (nx+1,ny)c f2 real workarray, dimensioned (nx,ny+1)c fil real inp filter-coeff., 0<afil<=1. Maximum filtering with afil=1c corresponds to one application of the linear filter.c misdat real inp missing-data value, a(i,j)=misdat indicates thatc the corresponding value is not available. Thec misdat-checking can be switched off with with misdat=0.c iperx int inp periodic boundaries in the x-direction (1=yes,0=no)c ipery int inp periodic boundaries in the y-direction (1=yes,0=no)c inpol int inp northpole at j=ny (1=yes,0=no)c ispol int inp southpole at j=1 (1=yes,0=no)cc Christoph Schaer, 1993c argument declarationinteger nx,nyreal a(nx,ny),af(nx,ny),fil,misdatinteger iperx,ipery,inpol,ispolc local variable declarationinteger i,j,isreal fhreal f1(nx+1,ny),f2(nx,ny+1)c compute constant fhfh=0.125*filc compute fluxes in x-directionif (misdat.eq.0.) thendo j=1,nydo i=2,nxf1(i,j)=a(i-1,j)-a(i,j)enddoenddoelsedo j=1,nydo i=2,nxif ((a(i,j).eq.misdat).or.(a(i-1,j).eq.misdat)) thenf1(i,j)=0.elsef1(i,j)=a(i-1,j)-a(i,j)endifenddoenddoendifif (iperx.eq.1) thenc do periodic boundaries in the x-directiondo j=1,nyf1(1,j)=f1(nx,j)f1(nx+1,j)=f1(2,j)enddoelsec set boundary-fluxes to zerodo j=1,nyf1(1,j)=0.f1(nx+1,j)=0.enddoendifc compute fluxes in y-directionif (misdat.eq.0.) thendo j=2,nydo i=1,nxf2(i,j)=a(i,j-1)-a(i,j)enddoenddoelsedo j=2,nydo i=1,nxif ((a(i,j).eq.misdat).or.(a(i,j-1).eq.misdat)) thenf2(i,j)=0.elsef2(i,j)=a(i,j-1)-a(i,j)endifenddoenddoendifc set boundary-fluxes to zerodo i=1,nxf2(i,1)=0.f2(i,ny+1)=0.enddoif (ipery.eq.1) thenc do periodic boundaries in the x-directiondo i=1,nxf2(i,1)=f2(i,ny)f2(i,ny+1)=f2(i,2)enddoendifif (iperx.eq.1) thenif (ispol.eq.1) thenc do south-poleis=(nx-1)/2do i=1,nxf2(i,1)=-f2(mod(i-1+is,nx)+1,2)enddoendifif (inpol.eq.1) thenc do north-poleis=(nx-1)/2do i=1,nxf2(i,ny+1)=-f2(mod(i-1+is,nx)+1,ny)enddoendifendifc compute flux-convergence -> filterif (misdat.eq.0.) thendo j=1,nydo i=1,nxaf(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))enddoenddoelsedo j=1,nydo i=1,nxif (a(i,j).eq.misdat) thenaf(i,j)=misdatelseaf(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))endifenddoenddoendifendc --------------------------------------------------------------------------------c Read refernece profile from netcdfc --------------------------------------------------------------------------------SUBROUTINE read_ref (nsqref,rhoref,thetaref,pressref,zref,> nx,ny,nz,deltax,deltay,deltaz,coriol,oro,> pvsrcfile)c Read the reference profile from filecc thetaref : Reference potential temperature (K)c pressref : Reference pressure (Pa)c rhoref : Reference density (kg/m^3)c nsqref : Stratification (s^-1)c zref : Reference height (m)c nx,nny,nz : Grid dimension in x,y,z directionc deltax,deltay,deltaz : Grid spacings used for calculations (m)c coriol : Coriolis parameter (s^-1)c oro : Height of orography (m)c pvsrcfile : Input fileimplicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal nsqref (0:2*nz)real thetaref(0:2*nz)real rhoref (0:2*nz)real pressref(0:2*nz)real zref (0:2*nz)real deltax,deltay,deltazreal coriol (0:nx,0:ny)real oro (0:nx,0:ny)character*80 pvsrcfilec Numerical and physical parametersreal epsparameter (eps=0.01)c Auxiliary variablesinteger cdfid,statinteger vardim(4)real misdatinteger ndiminreal varmin(4),varmax(4),stag(4)integer i,j,k,nf1integer ntimesreal time(200)character*80 vnam(100),varnameinteger nvarsinteger isok,ierrreal x(0:nx,0:ny),y(0:nx,0:ny)real mean,countc Get grid description from topographycall cdfopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 997call getvars(cdfid,nvars,vnam,stat)if (stat.ne.0) goto 997isok=0varname='ORO'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 997time(1)=0.call gettimes(cdfid,time,ntimes,stat)if (stat.ne.0) goto 997call clscdf(cdfid,stat)if (stat.ne.0) goto 997c Open output netcdf filecall cdfopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 997c Create the variable if necessarycall getvars(cdfid,nvars,vnam,stat)if (stat.ne.0) goto 997c Read data from netcdf fileisok=0varname='NSQREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,nsqref,stat)if (stat.ne.0) goto 997isok=0varname='RHOREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,rhoref,stat)if (stat.ne.0) goto 997isok=0varname='THETAREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,thetaref,stat)if (stat.ne.0) goto 997isok=0varname='PREREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,pressref,stat)if (stat.ne.0) goto 997isok=0varname='ZREF'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,zref,stat)if (stat.ne.0) goto 997isok=0varname='CORIOL'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,coriol,stat)if (stat.ne.0) goto 997isok=0varname='ORO'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,oro,stat)if (stat.ne.0) goto 997isok=0varname='X'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,x,stat)if (stat.ne.0) goto 997isok=0varname='Y'print*,'R ',trim(varname),' ',trim(pvsrcfile)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 997call getdat(cdfid,varname,time(1),0,y,stat)if (stat.ne.0) goto 997c Close netcdf filecall clscdf(cdfid,stat)if (stat.ne.0) goto 997c Determine the grid spacings <deltax, deltay, deltaz>mean=0.count=0.do i=1,nxdo j=0,nymean=mean+abs(x(i)-x(i-1))count=count+1.enddoenddodeltax=mean/countmean=0.count=0.do j=1,nydo i=0,nxmean=mean+abs(y(j)-y(j-1))count=count+1.enddoenddodeltay=mean/countmean=0.count=0.do k=1,nz-1mean=mean+abs(zref(k+1)-zref(k-1))count=count+1.enddodeltaz=mean/countreturnc Exception handling997 print*,'Read_Ref: Problem with input netcdf file... Stop'stopend