Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed
PROGRAM hydrostaticc Calculate the geopotential and add it to the P filec Michael Sprenger / Spring 2006implicit nonec ---------------------------------------------------------------c Declaration of variablesc ---------------------------------------------------------------c Variables for input P file : model levelcharacter*80 ml_pfnreal ml_varmin(4),ml_varmax(4),ml_stag(4)integer ml_vardim(4)real ml_mdvinteger ml_ndiminteger ml_nx,ml_ny,ml_nzreal ml_xmin,ml_xmax,ml_ymin,ml_ymax,ml_dx,ml_dyinteger ml_ntimesreal ml_aklev(500),ml_bklev(500)real ml_aklay(500),ml_bklay(500)real ml_timereal ml_pollon,ml_pollatinteger ml_nvarscharacter*80 ml_vnam(100)integer ml_idate(5)real,allocatable, dimension (:,:) :: ml_ps,ml_zbreal,allocatable, dimension (:,:,:) :: ml_t3,ml_q3,ml_p3,ml_tv3real,allocatable, dimension (:,:,:) :: ml_zlay3c Variables for input Z file : pressure levelcharacter*80 pl_zfnreal pl_varmin(4),pl_varmax(4),pl_stag(4)integer pl_vardim(4)real pl_mdvinteger pl_ndiminteger pl_nx,pl_ny,pl_nzreal pl_xmin,pl_xmax,pl_ymin,pl_ymax,pl_dx,pl_dyinteger pl_ntimesreal pl_aklev(500),pl_bklev(500)real pl_aklay(500),pl_bklay(500)real pl_timereal pl_pollon,pl_pollatinteger pl_nvarscharacter*80 pl_vnam(100)integer pl_idate(5)real,allocatable, dimension (:,:,:) :: pl_z3,pl_p3c Physical and numerical parametersreal gparameter (g=9.80665)real epsparameter (eps=0.01)real tzeroparameter (tzero=273.15)real kappaparameter (kappa=0.6078)real zerodivparameter (zerodiv=0.0000000001)real dpminparameter (dpmin=10.)real rdgparameter (rdg=29.271)c Auxiliary variablesinteger ierrinteger cdfid,cstidcharacter*80 cfninteger statreal timereal tv1(1000),z1(1000),p1(1000),f1(1000)real spline_tv1(1000),spline_f1(1000),spline_z1(1000)real pu,po,zu,zo,p,z,dp,p0,tvu,tvo,ffinteger i,j,k,linteger lmin,ncharacter*80 varname,cdfnameinteger isokinteger modec -----------------------------------------------------------------c Read input fieldsc -----------------------------------------------------------------print*,'*********************************************************'print*,'* hydrostatic *'print*,'*********************************************************'c Read in the parameter fileopen(10,file='fort.10')read(10,*) ml_pfnread(10,*) pl_zfnclose(10)c Decide which mode is used (1: reference from Z, 2: reference from ORO/PS)if ( trim(ml_pfn).ne.trim(pl_zfn) ) thenmode=1print*,'Taking reference from Z ',trim(pl_zfn)elsemode=2print*,'Taking reference from ORO/PS ',trim(pl_zfn)endifprint*,trim(ml_pfn)print*,trim(pl_zfn)c Get grid description for P file : model levelcall cdfopn(ml_pfn,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 getvars(cdfid,ml_nvars,ml_vnam,ierr)varname='T'isok=0call check_varok (isok,varname,ml_vnam,ml_nvars)if (isok.ne.1) goto 998call getdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,> ml_varmin,ml_varmax,ml_stag,ierr)if (ierr.ne.0) goto 998ml_nx =ml_vardim(1)ml_ny =ml_vardim(2)ml_nz =ml_vardim(3)ml_xmin=ml_varmin(1)ml_ymin=ml_varmin(2)call getlevs(cstid,ml_nz,ml_aklev,ml_bklev,ml_aklay,ml_bklay,ierr)call getgrid(cstid,ml_dx,ml_dy,ierr)ml_xmax=ml_xmin+real(ml_nx-1)*ml_dxml_ymax=ml_ymin+real(ml_ny-1)*ml_dycall gettimes(cdfid,ml_time,ml_ntimes,ierr)call getstart(cstid,ml_idate,ierr)call getpole(cstid,ml_pollon,ml_pollat,ierr)call clscdf(cstid,ierr)call clscdf(cdfid,ierr)c Get grid description reference: either ORO(P) or Z(Z)call cdfopn(pl_zfn,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 getvars(cdfid,pl_nvars,pl_vnam,ierr)if (mode.eq.1) thenvarname='Z'isok=0call check_varok (isok,varname,pl_vnam,pl_nvars)if (isok.ne.1) goto 998call getdef(cdfid,varname,pl_ndim,pl_mdv,pl_vardim,> pl_varmin,pl_varmax,pl_stag,ierr)if (ierr.ne.0) goto 998call getlevs(cstid,pl_nz,pl_aklev,pl_bklev,> pl_aklay,pl_bklay,ierr)call getgrid(cstid,pl_dx,pl_dy,ierr)call gettimes(cdfid,pl_time,pl_ntimes,ierr)call getstart(cstid,pl_idate,ierr)call getpole(cstid,pl_pollon,pl_pollat,ierr)else if (mode.eq.2) thenvarname='ORO'isok=0call check_varok (isok,varname,pl_vnam,pl_nvars)if (isok.ne.1) goto 998call getdef(cdfid,varname,pl_ndim,pl_mdv,pl_vardim,> pl_varmin,pl_varmax,pl_stag,ierr)if (ierr.ne.0) goto 998call getgrid(cstid,pl_dx,pl_dy,ierr)call gettimes(cdfid,pl_time,pl_ntimes,ierr)call getstart(cstid,pl_idate,ierr)call getpole(cstid,pl_pollon,pl_pollat,ierr)endifpl_nx =pl_vardim(1)pl_ny =pl_vardim(2)pl_nz =pl_vardim(3)pl_xmin=pl_varmin(1)pl_ymin=pl_varmin(2)pl_xmax=pl_xmin+real(pl_nx-1)*pl_dxpl_ymax=pl_ymin+real(pl_ny-1)*pl_dycall clscdf(cstid,ierr)call clscdf(cdfid,ierr)c Consitency check for the gridsif ( (ml_nx.ne.pl_nx).or.> (ml_ny.ne.pl_ny).or.> (abs(ml_xmin-pl_xmin ).gt.eps).or.> (abs(ml_ymin-pl_ymin ).gt.eps).or.> (abs(ml_xmax-pl_xmax ).gt.eps).or.> (abs(ml_ymax-pl_ymax ).gt.eps).or.> (abs(ml_dx -pl_dx ).gt.eps).or.> (abs(ml_dy -pl_dy ).gt.eps).or.> (abs(ml_time-pl_time ).gt.eps).or.> (abs(ml_pollon-pl_pollon).gt.eps).or.> (abs(ml_pollat-pl_pollat).gt.eps)) thenprint*,'Input P and Z grids are not consistent... Stop'print*,'Xmin ',ml_xmin ,pl_xminprint*,'Ymin ',ml_ymin ,pl_yminprint*,'Xmax ',ml_xmax ,pl_xmaxprint*,'Ymax ',ml_ymax ,pl_ymaxprint*,'Dx ',ml_dx ,pl_dxprint*,'Dy ',ml_dy ,pl_dyprint*,'Pollon ',ml_pollon ,pl_pollonprint*,'Pollat ',ml_pollat ,pl_pollatprint*,'Time ',ml_time ,pl_timestopendifc Allocate memory for all fieldsallocate(ml_ps(ml_nx,ml_ny),stat=stat)if (stat.ne.0) print*,'*** error allocating array ml_ps ***'allocate(ml_zb(ml_nx,ml_ny),stat=stat)if (stat.ne.0) print*,'*** error allocating array ml_zb ***'allocate(ml_p3(ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array ml_p3 ***'allocate(ml_t3(ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array ml_t3 ***'allocate(ml_q3(ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array ml_q3 ***'allocate(ml_tv3(ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array ml_tv3 ***'allocate(ml_zlay3(ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array ml_zlay3 ***'allocate(pl_z3(pl_nx,pl_ny,pl_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array pl_z3 ***'allocate(pl_p3(pl_nx,pl_ny,pl_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array pl_p3 ***'c Read T, Q, PS from P filecall cdfopn(ml_pfn,cdfid,ierr)if (ierr.ne.0) goto 998isok=0varname='T'call check_varok (isok,varname, ml_vnam,ml_nvars)varname='Q'call check_varok (isok,varname, ml_vnam,ml_nvars)varname='PS'call check_varok (isok,varname,ml_vnam,ml_nvars)if (isok.ne.3) goto 998print*,'R T ',trim(ml_pfn)call getdat(cdfid,'T',ml_time,0,ml_t3,ierr)print*,'R Q ',trim(ml_pfn)call getdat(cdfid,'Q',ml_time,0,ml_q3,ierr)print*,'R PS ',trim(ml_pfn)call getdat(cdfid,'PS',ml_time,1,ml_ps,ierr)call clscdf(cdfid,ierr)c Read ORO from P or Z from Z filecall cdfopn(pl_zfn,cdfid,ierr)if (ierr.ne.0) goto 998if (mode.eq.1) thenisok=0varname='Z'call check_varok (isok,varname,pl_vnam,pl_nvars)if (isok.ne.1) goto 998print*,'R Z ',trim(pl_zfn)call getdat(cdfid,varname,pl_time,0,pl_z3,ierr)else if (mode.eq.2) thenisok=0varname='ORO'call check_varok (isok,varname,pl_vnam,pl_nvars)if (isok.ne.1) goto 998print*,'R ORO ',trim(pl_zfn)call getdat(cdfid,varname,pl_time,1,pl_z3,ierr)endifcall clscdf(cdfid,ierr)c Set the values for the pressure on the pressure levelsdo i=1,pl_nxdo j=1,pl_nydo k=1,pl_nzif (mode.eq.1) thenpl_p3(i,j,k)=pl_aklay(k)else if (mode.eq.2) thenpl_p3(i,j,k)=ml_ps(i,j)endifenddoenddoenddoc Calculate 3d pressure fieldprint*,'C P'do k=1,ml_nzdo i=1,ml_nxdo j=1,ml_nyml_p3(i,j,k)=ml_aklay(k)+ml_bklay(k)*ml_ps(i,j)enddoenddoenddoc Calculate 3d virtual temperatureprint*,'C TV'do k=1,ml_nzdo i=1,ml_nxdo j=1,ml_nyml_tv3(i,j,k) = (ml_t3(i,j,k)+tzero)*> (1.+kappa*ml_q3(i,j,k))enddoenddoenddoc -----------------------------------------------------------------c Calculate geopotentialc -----------------------------------------------------------------c Integrate hydrostatic equation towards layersprint*,'C HYDROSTATIC EQUATION (LAYERS)'do i=1,ml_nxdo j=1,ml_nyc Make the virtual temperature profile availabledo k=1,ml_nzp1 (ml_nz-k+1)=ml_p3 (i,j,k)tv1(ml_nz-k+1)=ml_tv3(i,j,k)enddocall spline (p1,tv1,ml_nz,1.e30,1.e30,spline_tv1)c Loop over all model levelsdo k=1,ml_nzc Get pressure at the grid pointp = ml_aklay(k)+ml_bklay(k)*ml_ps(i,j)c Find nearest pressure level which is above topographyif (mode.eq.1) thenlmin=pl_nzdo l=1,pl_nzif ((abs(p-pl_p3(i,j,l))).lt.> (abs(p-pl_p3(i,j,lmin)))> .and.> (pl_p3(i,j,l).lt.ml_ps(i,j)) ) thenlmin=lendifenddoelse if (mode.eq.2) thenlmin=1endifc Integrate hydrostatic equation from this level to the grid pointp0 = pl_p3(i,j,lmin)n = nint(abs(p-p0)/dpmin)if (n.lt.1) n=1dp = (p-p0)/real(n)pu = p0z = pl_z3(i,j,lmin)call splint(p1,tv1,spline_tv1,ml_nz,pu,tvu)do l=1,npo = pu+dpcall splint(p1,tv1,spline_tv1,ml_nz,po,tvo)z = z + rdg*0.5*(tvu+tvo)*alog(pu/po)tvu = tvopu = poenddoc Set the geopotential at the grid pointml_zlay3(i,j,k) = zenddoenddoenddoc -----------------------------------------------------------------c Calculate height of topographyc -----------------------------------------------------------------if (mode.eq.1) thenprint*,'C TOPOGRAPHY'do i=1,ml_nxdo j=1,ml_nyc Make the z/p profile availabledo k=1,ml_nzp1(ml_nz-k+1)=ml_p3(i,j,k)z1(ml_nz-k+1)=ml_zlay3(i,j,k)enddoc Cubic spline interpolationcall spline (p1,z1,ml_nz,1.e30,1.e30,spline_z1)call splint (p1,z1,spline_z1,ml_nz,ml_ps(i,j),ml_zb(i,j))enddoenddoendifc -----------------------------------------------------------------c Write the topography and geopotential to P filec -----------------------------------------------------------------c Open P filecall cdfwopn(trim(ml_pfn),cdfid,ierr)c Write orography (levels)if (mode.eq.1) thenvarname='ORO'print*,'W ',trim(varname),' ',trim(ml_pfn)isok=0call check_varok (isok,varname,ml_vnam,ml_nvars)if (isok.eq.0) thenml_vardim(3)=1call putdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,> ml_varmin,ml_varmax,ml_stag,ierr)ml_vardim(3)=ml_nzif (ierr.ne.0) goto 997endifcall putdat(cdfid,varname,ml_time,1,ml_zb,ierr)if (ierr.ne.0) goto 997endifc Write geopotential on layersvarname='Z_DIA'print*,'W ',trim(varname),' ',trim(ml_pfn)isok=0call check_varok (isok,varname,ml_vnam,ml_nvars)if (isok.eq.0) thenml_stag(3)=-0.5call putdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,> ml_varmin,ml_varmax,ml_stag,ierr)if (ierr.ne.0) goto 997endifcall putdat(cdfid,varname,ml_time,0,ml_zlay3,ierr)if (ierr.ne.0) goto 997c Close P filecall clscdf(cdfid,ierr)c -----------------------------------------------------------------c Exception handling and format specsc -----------------------------------------------------------------stop998 print*,'Z: Problems with input from m level'stop997 print*,'Z: Problems with output on m level'stop996 print*,'F: Problems with input from m level'stop995 print*,'F: Problems with output on z level'stopendc -------------------------------------------------------------c Natural cubic splinec -------------------------------------------------------------SUBROUTINE spline(x,y,n,yp1,ypn,y2)INTEGER n,NMAXREAL yp1,ypn,x(n),y(n),y2(n)PARAMETER (NMAX=500)INTEGER i,kREAL p,qn,sig,un,u(NMAX)if (yp1.gt..99e30) theny2(1)=0.u(1)=0.elsey2(1)=-0.5u(1)=(3./(x(2)-x(1)))*((y(2)-y(1))/(x(2)-x(1))-yp1)endifdo 11 i=2,n-1sig=(x(i)-x(i-1))/(x(i+1)-x(i-1))p=sig*y2(i-1)+2.y2(i)=(sig-1.)/pu(i)=(6.*((y(i+1)-y(i))/(x(i+*1)-x(i))-(y(i)-y(i-1))/(x(i)-x(i-1)))/(x(i+1)-x(i-1))-sig**u(i-1))/p11 continueif (ypn.gt..99e30) thenqn=0.un=0.elseqn=0.5un=(3./(x(n)-x(n-1)))*(ypn-(y(n)-y(n-1))/(x(n)-x(n-1)))endify2(n)=(un-qn*u(n-1))/(qn*y2(n-1)+1.)do 12 k=n-1,1,-1y2(k)=y2(k)*y2(k+1)+u(k)12 continuereturnENDSUBROUTINE splint(xa,ya,y2a,n,x,y)INTEGER nREAL x,y,xa(n),y2a(n),ya(n)INTEGER k,khi,kloREAL a,b,hklo=1khi=n1 if (khi-klo.gt.1) thenk=(khi+klo)/2if(xa(k).gt.x)thenkhi=kelseklo=kendifgoto 1endifh=xa(khi)-xa(klo)if (h.eq.0.) pause 'bad xa input in splint'a=(xa(khi)-x)/hb=(x-xa(klo))/hy=a*ya(klo)+b*ya(khi)+((a**3-a)*y2a(klo)+(b**3-b)*y2a(khi))*(h***2)/6.returnENDc ----------------------------------------------------------------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+1enddoend