Blame | Last modification | View Log | Download | RSS feed
PROGRAM rotate_laloc *******************************************************************c * Rotate to a geographical latitude/longitude grid *c * Michael Sprenger / Autumn 2006 *c *******************************************************************implicit nonec -------------------------------------------------------------------c Declaration of parameters and variablesc -------------------------------------------------------------------c Specification of input parametersreal clon,clat,rotationinteger nx,nyreal dx,dy,xmin,ymininteger nfieldcharacter*80 fieldname(100)c Numerical and physical parametersreal degradparameter (degrad=0.0174532925)real omegaerdparameter (omegaerd=7.292e-5 )real epsparameter (eps=0.001)c Variables for input Z file : height levelcharacter*80 in_cfnreal in_varmin(4),in_varmax(4),in_stag(4)integer in_vardim(4)real in_mdvinteger in_ndiminteger in_nx,in_ny,in_nzreal in_xmin,in_xmax,in_ymin,in_ymax,in_dx,in_dyinteger in_ntimesreal in_aklev(500),in_bklev(500)real in_aklay(500),in_bklay(500)real in_timereal in_pollon,in_pollatinteger in_nvarscharacter*80 in_vnam(100)integer in_idate(5)real,allocatable, dimension (:,:,:) :: in_field3real,allocatable, dimension (:,:,:) :: in_vect1real,allocatable, dimension (:,:,:) :: in_vect2c Variables for output Z file : height levelcharacter*80 out_cfnreal out_varmin(4),out_varmax(4),out_stag(4)integer out_vardim(4)real out_mdvinteger out_ndiminteger out_nx,out_ny,out_nzreal out_xmin,out_xmax,out_ymin,out_ymax,out_dx,out_dyinteger out_ntimesreal out_aklev(500),out_bklev(500)real out_aklay(500),out_bklay(500)real out_timereal out_pollon,out_pollatinteger out_idate(5)real,allocatable, dimension (:,:,:) :: out_field3real,allocatable, dimension (:,:,:) :: out_vect1real,allocatable, dimension (:,:,:) :: out_vect2real,allocatable, dimension (:,:) :: out_lat,out_lonreal,allocatable, dimension (:,:) :: out_x,out_yreal,allocatable, dimension (:,:) :: out_coriolc Auxiliary variablesinteger ifieldinteger i,j,kinteger cdfid,cstidcharacter*80 cfninteger stat,ierr,isokreal timecharacter*80 varname,cdfname,varname1,varname2integer idate(5),stdate(5),datar(14)integer rotmodeinteger i1,i2,i3,i4integer isvectorreal latcharacter*80 namec Externalsreal sdisexternal sdisc -------------------------------------------------------------------c Preparationsc -------------------------------------------------------------------print*,'*********************************************************'print*,'* rotate_lalo *'print*,'*********************************************************'c Read parameter fileopen(10,file='fort.10')read(10,*) in_cfnread(10,*) out_cfnread(10,*) name,nxif ( trim(name).ne.'GEO_NX' ) stopread(10,*) name,nyif ( trim(name).ne.'GEO_NY' ) stopread(10,*) name,dxif ( trim(name).ne.'GEO_DX' ) stopread(10,*) name,dyif ( trim(name).ne.'GEO_DY' ) stopread(10,*) name,xminif ( trim(name).ne.'GEO_XMIN') stopread(10,*) name,yminif ( trim(name).ne.'GEO_YMIN') stopread(10,*) name,clonif ( trim(name).ne.'CLON' ) stopread(10,*) name,clatif ( trim(name).ne.'CLAT' ) stopread(10,*) name,rotationif ( trim(name).ne.'CROT' ) stopread(10,*) nfielddo i=1,nfieldread(10,*) fieldname(i)enddoclose(10)print*,clon,clat,rotationprint*,nx,ny,dx,dy,xmin,yminprint*,trim(in_cfn),' -> ',trim(out_cfn)c Get grid description for input Z file : height levelcall cdfopn(in_cfn,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,in_nvars,in_vnam,ierr)if (ierr.ne.0) goto 998isok=0varname=fieldname(1)call check_varok (isok,varname,in_vnam,in_nvars)if (isok.eq.0) goto 998call getdef(cdfid,varname,in_ndim,in_mdv,in_vardim,> in_varmin,in_varmax,in_stag,ierr)if (ierr.ne.0) goto 998in_nx =in_vardim(1)in_ny =in_vardim(2)in_xmin=in_varmin(1)in_ymin=in_varmin(2)call getlevs(cstid,in_nz,in_aklev,in_bklev,in_aklay,in_bklay,ierr)call getgrid(cstid,in_dx,in_dy,ierr)in_xmax=in_xmin+real(in_nx-1)*in_dxin_ymax=in_ymin+real(in_ny-1)*in_dycall gettimes(cdfid,in_time,in_ntimes,ierr)call getstart(cstid,in_idate,ierr)call getpole(cstid,in_pollon,in_pollat,ierr)call clscdf(cstid,ierr)call clscdf(cdfid,ierr)c Set grid description for output file : height levelout_vardim(1) = nxout_vardim(2) = nyout_vardim(3) = in_nzout_varmin(1) = xminout_varmin(2) = yminout_varmin(3) = in_varmin(3)out_varmax(1) = xmin+real(nx-1)*dxout_varmax(2) = ymin+real(ny-1)*dyout_varmax(3) = in_varmax(3)do i=1,in_nzout_aklay(i) = in_aklay(i)out_bklay(i) = in_bklay(i)out_aklev(i) = in_aklev(i)out_bklev(i) = in_bklev(i)enddoout_dx = dxout_dy = dyout_time = in_timeout_ntimes = in_ntimesout_ndim = 4out_mdv = in_mdvout_nx = out_vardim(1)out_ny = out_vardim(2)out_nz = out_vardim(3)out_xmin = out_varmin(1)out_ymin = out_varmin(2)out_pollon = 0.out_pollat = 90.do i=1,5out_idate(i) = in_idate(i)enddoc Allocate memory for all fieldsallocate(in_field3(in_nx,in_ny,in_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array in_field3 ***'allocate(in_vect1(in_nx,in_ny,in_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array in_vect1 ***'allocate(in_vect2(in_nx,in_ny,in_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array in_vect2 ***'allocate(out_field3(out_nx,out_ny,out_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array out_field3 ***'allocate(out_vect1(out_nx,out_ny,out_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array out_vect1 ***'allocate(out_vect2(out_nx,out_ny,out_nz),stat=stat)if (stat.ne.0) print*,'*** error allocating array out_vect2 ***'allocate(out_lat(out_nx,out_ny),stat=stat)if (stat.ne.0) print*,'*** error allocating array out_lat ***'allocate(out_lon(out_nx,out_ny),stat=stat)if (stat.ne.0) print*,'*** error allocating array out_lon ***'allocate(out_x(out_nx,out_ny),stat=stat)if (stat.ne.0) print*,'*** error allocating array out_x ***'allocate(out_y(out_nx,out_ny),stat=stat)if (stat.ne.0) print*,'*** error allocating array out_y ***'allocate(out_coriol(out_nx,out_ny),stat=stat)if (stat.ne.0) print*,'*** error allocating array out_coriol ***'c Create constants file and output file (if requested)datar(1)=out_nxdatar(2)=out_nydatar(3)=int(1000.*out_varmax(2))datar(4)=int(1000.*out_varmin(1))datar(5)=int(1000.*out_varmin(2))datar(6)=int(1000.*out_varmax(1))datar(7)=int(1000.*out_dx)datar(8)=int(1000.*out_dy)datar(9)=out_nzdatar(10)=1datar(11)=1datar(12)=0datar(13)=int(1000.*out_pollon)datar(14)=int(1000.*out_pollat)cfn=trim(out_cfn)//'_cst'call wricst(cfn,datar,out_aklev,out_bklev,> out_aklay,out_bklay,out_idate)call crecdf(trim(out_cfn),cdfid,out_varmin,out_varmax,> out_ndim,trim(cfn),ierr)if (ierr.ne.0) goto 997call clscdf(cdfid,ierr)c -----------------------------------------------------------------c Loop through all fields - rotate to new gridc -----------------------------------------------------------------do ifield=1,nfieldc Check if scalar or vectorial field (X for scalar, U.V for vector)varname=fieldname(ifield)i1=1i2=1i3=0i4=0100 if (varname(i1:i1).eq.' ') theni1=i1+1goto 100endifi2=i1101 if ((varname(i2:i2).ne.' ').and.(varname(i2:i2).ne.'.')) theni2=i2+1goto 101endifif (varname(i2:i2).eq.'.') theni3=i2+1102 if (varname(i3:i3).eq.' ') theni3=i3+1goto 102endifi4=i3104 if (varname(i4:i4).ne.' ') theni4=i4+1goto 104endifendifif ((i3.ne.0).and.(i4.ne.0)) thenisvector=1i2=i2-1varname1=varname(i1:i2)i4=i4-1varname2=varname(i3:i4)print*,'Rotating vector : ',> trim(varname1),' / ',trim(varname2)elseisvector=0i2=i2-1varname=varname(i1:i2)print*,'Rotating scalar : ',trim(varname)endifc Rotate a scalar fieldif (isvector.eq.0) thenc Read input fieldcall cdfopn(in_cfn,cdfid,ierr)if (ierr.ne.0) goto 998call getdef(cdfid,varname,in_ndim,in_mdv,in_vardim,> in_varmin,in_varmax,in_stag,ierr)in_nz=in_vardim(3)if (ierr.ne.0) goto 998call getdat(cdfid,varname,in_time,0,in_field3,ierr)if (ierr.ne.0) goto 998call clscdf(cdfid,ierr)c Rotate to new coordinate systemout_nz=in_nzcall getenvir (clon,clat,rotation,0,> in_field3,in_dx,in_dy,> in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,> out_field3,out_dx,out_dy,> out_xmin,out_ymin,out_nx,out_ny,out_nz)c Write output scalar fieldcall cdfwopn(trim(out_cfn),cdfid,ierr)if (ierr.ne.0) goto 997out_vardim(3)=out_nzcall putdef(cdfid,varname,4,out_mdv,out_vardim,> out_varmin,out_varmax,out_stag,ierr)if (ierr.ne.0) goto 997call putdat(cdfid,varname,out_time,0,out_field3,ierr)if (ierr.ne.0) goto 997call clscdf(cdfid,ierr)c Rotate vector fieldelse if (isvector.eq.1) thenc Read input vector fieldcall cdfopn(in_cfn,cdfid,ierr)if (ierr.ne.0) goto 998call getdef(cdfid,varname1,in_ndim,in_mdv,in_vardim,> in_varmin,in_varmax,in_stag,ierr)in_nz=in_vardim(3)if (ierr.ne.0) goto 998call getdat(cdfid,varname1,in_time,0,in_vect1,ierr)if (ierr.ne.0) goto 998call getdef(cdfid,varname2,in_ndim,in_mdv,in_vardim,> in_varmin,in_varmax,in_stag,ierr)in_nz=in_vardim(3)if (ierr.ne.0) goto 998call getdat(cdfid,varname2,in_time,0,in_vect2,ierr)if (ierr.ne.0) goto 998call clscdf(cdfid,ierr)c Get new vector component in x directionout_nz=in_nzcall getenvir (clon,clat,rotation,1,> in_vect1,in_dx,in_dy,> in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,> out_field3,out_dx,out_dy,> out_xmin,out_ymin,out_nx,out_ny,out_nz)do i=1,out_nxdo j=1,out_nydo k=1,out_nzout_vect1(i,j,k)=out_field3(i,j,k)enddoenddoenddocall getenvir (clon,clat,rotation,2,> in_vect2,in_dx,in_dy,> in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,> out_field3,out_dx,out_dy,> out_xmin,out_ymin,out_nx,out_ny,out_nz)do i=1,out_nxdo j=1,out_nydo k=1,out_nzif ( (abs(out_vect1 (i,j,k)-out_mdv).gt.eps).and.> (abs(out_field3(i,j,k)-out_mdv).gt.eps) ) thenout_vect1(i,j,k)=out_vect1(i,j,k)-> out_field3(i,j,k)endifenddoenddoenddoc Get new vector component in y directionout_nz=in_nzcall getenvir (clon,clat,rotation,2,> in_vect1,in_dx,in_dy,> in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,> out_field3,out_dx,out_dy,> out_xmin,out_ymin,out_nx,out_ny,out_nz)do i=1,out_nxdo j=1,out_nydo k=1,out_nzout_vect2(i,j,k)=out_field3(i,j,k)enddoenddoenddocall getenvir (clon,clat,rotation,1,> in_vect2,in_dx,in_dy,> in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,> out_field3,out_dx,out_dy,> out_xmin,out_ymin,out_nx,out_ny,out_nz)do i=1,out_nxdo j=1,out_nydo k=1,out_nzif ( (abs(out_vect2 (i,j,k)-out_mdv).gt.eps).and.> (abs(out_field3(i,j,k)-out_mdv).gt.eps) ) thenout_vect2(i,j,k)=out_vect2(i,j,k)+> out_field3(i,j,k)endifenddoenddoenddoc Write output vector fieldcall cdfwopn(trim(out_cfn),cdfid,ierr)if (ierr.ne.0) goto 997out_vardim(3)=out_nzcall putdef(cdfid,varname1,4,out_mdv,out_vardim,> out_varmin,out_varmax,out_stag,ierr)if (ierr.ne.0) goto 997call putdat(cdfid,varname1,out_time,0,out_vect1,ierr)if (ierr.ne.0) goto 997call putdef(cdfid,varname2,4,out_mdv,out_vardim,> out_varmin,out_varmax,out_stag,ierr)if (ierr.ne.0) goto 997call putdat(cdfid,varname2,out_time,0,out_vect2,ierr)if (ierr.ne.0) goto 997call clscdf(cdfid,ierr)endifenddoc -----------------------------------------------------------------c Write additional fields: latitude, longitude, Coriolis parameterc -----------------------------------------------------------------c Open the output filecall cdfwopn(trim(out_cfn),cdfid,ierr)if (ierr.ne.0) goto 997c Geographical latitudevarname='RLAT'print*,'Rotating scalar : ',trim(varname)do i=1,in_nxdo j=1,in_nyin_field3(i,j,1)=in_ymin+real(j-1)*in_dyenddoenddocall getenvir (clon,clat,rotation,0,> in_field3,in_dx,in_dy,> in_xmin,in_ymin,in_nx,in_ny,1,in_mdv,> out_lat,out_dx,out_dy,> out_xmin,out_ymin,out_nx,out_ny,1)out_vardim(3)=1call putdef(cdfid,varname,4,out_mdv,out_vardim,> out_varmin,out_varmax,out_stag,ierr)if (ierr.ne.0) goto 997call putdat(cdfid,varname,out_time,0,out_lat,ierr)if (ierr.ne.0) goto 997c Geographical longitudevarname='RLON'print*,'Rotating scalar : ',trim(varname)do i=1,in_nxdo j=1,in_nyin_field3(i,j,1)=in_xmin+real(i-1)*in_dxenddoenddocall getenvir (clon,clat,rotation,0,> in_field3,in_dx,in_dy,> in_xmin,in_ymin,in_nx,in_ny,1,in_mdv,> out_lon,out_dx,out_dy,> out_xmin,out_ymin,out_nx,out_ny,1)out_vardim(3)=1call putdef(cdfid,varname,4,out_mdv,out_vardim,> out_varmin,out_varmax,out_stag,ierr)if (ierr.ne.0) goto 997call putdat(cdfid,varname,out_time,0,out_lon,ierr)if (ierr.ne.0) goto 997c Close output filecall clscdf(cdfid,ierr)c -----------------------------------------------------------------c Exception handling and format specsc -----------------------------------------------------------------stop998 print*,'Z: Problems with input rotated grid'stop997 print*,'Z: Problems with output to lat/lon grid'stopendc ********************************************************************************c * SUBROUTINE: ROTATION TO LATITUDE/LONGITUDE COORDINATE SYSTEM *c ********************************************************************************c --------------------------------------------------------------------------------c Subroutine to get environment of strcofc --------------------------------------------------------------------------------SUBROUTINE getenvir (clon,clat,rotation,rotmode,> inar, rdx,rdy,rxmin,rymin,rnx,rny,rnz,mdv,> outar, dx, dy, xmin, ymin, nx, ny, nz)c Rotate from a local quasi-cartesian coordiante system into lat/lon coordinatec system.implicit nonec Declaration of input parametersinteger rnx,rny,rnzreal rdx,rdy,rxmin,ryminreal inar(rnx,rny,rnz)real clon,clat,rotationreal mdvinteger rotmodec Declaration of output parametersinteger nx,ny,nzreal dx,dy,xmin,yminreal outar(nx,ny,nz)c Set numerical and physical constantsreal g2rparameter (g2r=0.0174533)real pi180parameter (pi180=3.14159265359/180.)real epsparameter (eps=0.0001)c Flag for test modeinteger testparameter (test=0)character*80 testfileparameter (testfile='ROTGRID')c Auxiliary variablesreal pollon,pollatinteger i,j,k,lreal rlon(nx,ny),rlat(nx,ny)real rlon1(nx,ny),rlat1(nx,ny)real lon(nx,ny),lat(nx,ny)real rotangle1(nx,ny),rotangle2(nx,ny)real rotangle(nx,ny)real sinoutar(nx,ny,nz),cosoutar(nx,ny,nz)real rxmax,rymaxreal xind,yind,pindreal outvalinteger ix,iyreal ax,ay,az,bx,by,bz,zx,zy,zzreal clon1,clat1,clon2,clat2real rindx,rindyinteger indx,indy,indr,indureal frac0i,frac0j,frac1i,frac1jcharacter*80 cdfname,varname,cstnamereal vx1,vx2,vy1,vy2,angle,vx2mininteger sc Externalsreal lmtolms,phtophsexternal lmtolms,phtophsc Get geographical coordinatesdo i=1,nxdo j=1,nylon(i,j)=xmin+real(i-1)*dxlat(i,j)=ymin+real(j-1)*dyenddoenddoc First rotationpollon=clon-180.if (pollon.lt.-180.) pollon=pollon+360.pollat=90.-clatdo i=1,nxdo j=1,nyrlon1(i,j)=lmtolms(lat(i,j),lon(i,j),pollat,pollon)rlat1(i,j)=phtophs(lat(i,j),lon(i,j),pollat,pollon)enddoenddoc Second coordinate transformationpollon=-180.pollat=90.+rotationdo i=1,nxdo j=1,nyrlon(i,j)=90.+lmtolms(rlat1(i,j),rlon1(i,j)-90.,pollat,pollon)rlat(i,j)=phtophs(rlat1(i,j),rlon1(i,j)-90.,pollat,pollon)enddoenddoc Get the angle between the rotated and non-rotated coordinate frameif ((rotmode.eq.1).or.(rotmode.eq.2)) thendo i=2,nx-1do j=2,ny-1c Angle between latitude circlesvx1=1.vy1=0.vx2min=(rlon(i+1,j)-rlon(i-1,j))*cos(pi180*rlat(i,j))do s=-1,1,2vx2=(rlon(i+1,j)-rlon(i-1,j)+real(s)*360.)*> cos(pi180*rlat(i,j))if (abs(vx2).lt.abs(vx2min)) vx2min=vx2enddovx2=vx2minvy2=rlat(i+1,j)-rlat(i-1,j)call getangle(vx1,vy1,vx2,vy2,angle)rotangle1(i,j)=anglec Angle between longitude circlesvx1=0.vy1=1.vx2min=(rlon(i,j+1)-rlon(i,j-1))*cos(pi180*rlat(i,j))do s=-1,1,2vx2=(rlon(i+1,j)-rlon(i-1,j)+real(s)*360.)*> cos(pi180*rlat(i,j))if (abs(vx2).lt.abs(vx2min)) vx2min=vx2enddovx2=vx2minvy2=rlat(i,j+1)-rlat(i,j-1)call getangle(vx1,vy1,vx2,vy2,angle)rotangle2(i,j)=angleenddoenddoc Set the angle at the boundariesdo i=1,nxrotangle1(i,ny)=2.0*rotangle1(i,ny-1)-rotangle1(i,ny-2)rotangle1(i,1) =2.0*rotangle1(i,2)-rotangle1(i,3)rotangle2(i,ny)=2.0*rotangle2(i,ny-1)-rotangle2(i,ny-2)rotangle2(i,1) =2.0*rotangle2(i,2)-rotangle2(i,3)enddodo j=1,nyrotangle1(nx,j)=2.0*rotangle1(nx-1,j)-rotangle1(nx-2,j)rotangle1(1,j) =2.0*rotangle1(2,j)-rotangle1(3,j)rotangle2(nx,j)=2.0*rotangle2(nx-1,j)-rotangle2(nx-2,j)rotangle2(1,j) =2.0*rotangle2(2,j)-rotangle2(3,j)enddoc Set the final rotation angledo i=1,nxdo j=1,nyrotangle(i,j)=0.5*(rotangle1(i,j)+rotangle2(i,j))enddoenddoendifc Bring longitude into domain of geographical grid (shift by 360 deg)do i=1,nxdo j=1,ny100 if (rlon(i,j).lt.rxmin) thenrlon(i,j)=rlon(i,j)+360.goto 100endif102 if (rlon(i,j).gt.(rxmin+real(rnx-1)*rdx)) thenrlon(i,j)=rlon(i,j)-360.goto 102endifenddoenddoc Rotate the scalar or the vector componentdo i=1,nxdo j=1,nydo k=1,nzc Get indexrindx=(rlon(i,j)-rxmin)/rdx+1.rindy=(rlat(i,j)-rymin)/rdy+1.indx=int(rindx)indy=int(rindy)if ((indx.lt.1).or.(indx.gt.rnx).or.> (indy.lt.1).or.(indy.gt.rny)) thenoutar(i,j,k)=mdvgoto 103endifc Get inidices of left and upper neighboursindr=indx+1if (indr.gt.rnx) indr=1indu=indy+1if (indu.gt.rny) indu=nyc Do linear interpolationif ( ( abs(inar(indx ,indy, k)-mdv).gt.eps ).and.& ( abs(inar(indx ,indu, k)-mdv).gt.eps ).and.& ( abs(inar(indr ,indy, k)-mdv).gt.eps ).and.& ( abs(inar(indr ,indu, k)-mdv).gt.eps ) ) thenfrac0i=rindx-float(indx)frac0j=rindy-float(indy)frac1i=1.-frac0ifrac1j=1.-frac0joutval = inar(indx ,indy, k ) * frac1i * frac1j& + inar(indx ,indu, k ) * frac1i * frac0j& + inar(indr ,indy, k ) * frac0i * frac1j& + inar(indr ,indu, k ) * frac0i * frac0jelseoutval=mdvendifc Update output arrayoutar(i,j,k)=outvalc Next103 continueenddoenddoenddoc Get components for testsif (test.eq.1) thendo i=1,nxdo j=1,nydo k=1,nzcosoutar(i,j,k)=outar(i,j,k)*cos(pi180*rotangle(i,j))sinoutar(i,j,k)=-outar(i,j,k)*sin(pi180*rotangle(i,j))enddoenddoenddoendifc Get correct component of rotated fielddo i=1,nxdo j=1,nydo k=1,nzif ( abs(outar(i,j,k)-mdv).gt.eps ) thenif (rotmode.eq.1) thenoutar(i,j,k)= outar(i,j,k)*cos(pi180*rotangle(i,j))else if (rotmode.eq.2) thenoutar(i,j,k)=-outar(i,j,k)*sin(pi180*rotangle(i,j))else if (rotmode.eq.0) thenoutar(i,j,k)=outar(i,j,k)endifendifenddoenddoenddoc Test mode: Write grids to cdf fileif (test.eq.1) thencdfname=testfilecstname=trim(testfile)//'_cst'varname='RLON1'call writecdf2D(cdfname,cstname,> varname,rlon1,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 1,1)cdfname=testfilecstname=trim(testfile)//'_cst'varname='RLON'call writecdf2D(cdfname,cstname,> varname,rlon,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 0,1)cdfname=testfilecstname=trim(testfile)//'_cst'varname='LON'call writecdf2D(cdfname,cstname,> varname,lon,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 0,1)cdfname=testfilecstname=trim(testfile)//'_cst'varname='RLAT1'call writecdf2D(cdfname,cstname,> varname,rlat1,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 0,1)cdfname=testfilecstname=trim(testfile)//'_cst'varname='RLAT'call writecdf2D(cdfname,cstname,> varname,rlat,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 0,1)cdfname=testfilecstname=trim(testfile)//'_cst'varname='LAT'call writecdf2D(cdfname,cstname,> varname,lat,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 0,1)cdfname=testfilecstname=trim(testfile)//'_cst'varname='ANGLE1'call writecdf2D(cdfname,cstname,> varname,rotangle1,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 0,1)cdfname=testfilecstname=trim(testfile)//'_cst'varname='ANGLE2'call writecdf2D(cdfname,cstname,> varname,rotangle2,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 0,1)cdfname=testfilecstname=trim(testfile)//'_cst'varname='U'call writecdf2D(cdfname,cstname,> varname,cosoutar,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 0,1)cdfname=testfilecstname=trim(testfile)//'_cst'varname='V'call writecdf2D(cdfname,cstname,> varname,sinoutar,0.,> rdx,rdy,rxmin,rymin,rnx,rny,> 0,1)endifENDc --------------------------------------------------------------------------------c Auxiliary routines: angle between two vectorsc --------------------------------------------------------------------------------SUBROUTINE getangle (vx1,vy1,vx2,vy2,angle)c Given two vectors <vx1,vy1> and <vx2,vy2>, determine the angle (in deg)c between the two vectors.implicit nonec Declaration of subroutine parametersreal vx1,vy1real vx2,vy2real anglec Auxiliary variables and parametersreal len1,len2,len3real val1,val2,val3real piparameter (pi=3.14159265359)len1=sqrt(vx1*vx1+vy1*vy1)len2=sqrt(vx2*vx2+vy2*vy2)if ((len1.gt.0.).and.(len2.gt.0.)) thenvx1=vx1/len1vy1=vy1/len1vx2=vx2/len2vy2=vy2/len2val1=vx1*vx2+vy1*vy2val2=-vy1*vx2+vx1*vy2len3=sqrt(val1*val1+val2*val2)if ( (val1.ge.0.).and.(val2.ge.0.) ) thenval3=acos(val1/len3)else if ( (val1.lt.0.).and.(val2.ge.0.) ) thenval3=pi-acos(abs(val1)/len3)else if ( (val1.ge.0.).and.(val2.le.0.) ) thenval3=-acos(val1/len3)else if ( (val1.lt.0.).and.(val2.le.0.) ) thenval3=-pi+acos(abs(val1)/len3)endifelseval3=0.endifangle=180./pi*val3ENDc --------------------------------------------------------------------------------c Transformation routine: LMSTOLM and PHSTOPH from library gm2emc --------------------------------------------------------------------------------REAL FUNCTION LMTOLMS (PHI, LAM, POLPHI, POLLAM)CC%Z% Modul %M%, V%I% vom %G%, extrahiert am %H%CC**** LMTOLMS - FC:UMRECHNUNG DER WAHREN GEOGRAPHISCHEN LAENGE LAMC**** AUF EINEM PUNKT MIT DEN KOORDINATEN (PHIS, LAMS)C**** IM ROTIERTEN SYSTEM. DER NORDPOL DES SYSTEMS HATC**** DIE WAHREN KOORDINATEN (POLPHI, POLLAM)C** AUFRUF : LAM = LMTOLMS (PHI, LAM, POLPHI, POLLAM)C** ENTRIES : KEINEC** ZWECK : UMRECHNUNG DER WAHREN GEOGRAPHISCHEN LAENGE LAM AUFC** EINEM PUNKT MIT DEN KOORDINATEN (PHIS, LAMS) IMC** ROTIERTEN SYSTEM. DER NORDPOL DIESES SYSTEMS HATC** DIE WAHREN KOORDINATEN (POLPHI, POLLAM)C** VERSIONS-C** DATUM : 03.05.90C**C** EXTERNALS: KEINEC** EINGABE-C** PARAMETER: PHI REAL BREITE DES PUNKTES IM GEOGR. SYSTEMC** LAM REAL LAENGE DES PUNKTES IM GEOGR. SYSTEMC** POLPHI REAL GEOGR.BREITE DES N-POLS DES ROT. SYSTEMSC** POLLAM REAL GEOGR.LAENGE DES N-POLS DES ROT. SYSTEMSC** AUSGABE-C** PARAMETER: WAHRE GEOGRAPHISCHE LAENGE ALS WERT DER FUNKTIONC** ALLE WINKEL IN GRAD (NORDEN>0, OSTEN>0)C**C** COMMON-C** BLOECKE : KEINEC**C** FEHLERBE-C** HANDLUNG : KEINEC** VERFASSER: G. DE MORSIERREAL LAM,PHI,POLPHI,POLLAMDATA ZRPI18 , ZPIR18 / 57.2957795 , 0.0174532925 /ZSINPOL = SIN(ZPIR18*POLPHI)ZCOSPOL = COS(ZPIR18*POLPHI)ZLAMPOL = ZPIR18*POLLAMZPHI = ZPIR18*PHIZLAM = LAMIF(ZLAM.GT.180.0) ZLAM = ZLAM - 360.0ZLAM = ZPIR18*ZLAMZARG1 = - SIN(ZLAM-ZLAMPOL)*COS(ZPHI)ZARG2 = - ZSINPOL*COS(ZPHI)*COS(ZLAM-ZLAMPOL)+ZCOSPOL*SIN(ZPHI)IF (ABS(ZARG2).LT.1.E-30) THENIF (ABS(ZARG1).LT.1.E-30) THENLMTOLMS = 0.0ELSEIF (ZARG1.GT.0.) THENLMTOLMS = 90.0ELSELMTOLMS = -90.0ENDIFELSELMTOLMS = ZRPI18*ATAN2(ZARG1,ZARG2)ENDIFRETURNENDREAL FUNCTION PHTOPHS (PHI, LAM, POLPHI, POLLAM)CC%Z% Modul %M%, V%I% vom %G%, extrahiert am %H%CC**** PHTOPHS - FC:UMRECHNUNG DER WAHREN GEOGRAPHISCHEN BREITE PHIC**** AUF EINEM PUNKT MIT DEN KOORDINATEN (PHIS, LAMS)C**** IM ROTIERTEN SYSTEM. DER NORDPOL DES SYSTEMS HATC**** DIE WAHREN KOORDINATEN (POLPHI, POLLAM)C** AUFRUF : PHI = PHTOPHS (PHI, LAM, POLPHI, POLLAM)C** ENTRIES : KEINEC** ZWECK : UMRECHNUNG DER WAHREN GEOGRAPHISCHEN BREITE PHI AUFC** EINEM PUNKT MIT DEN KOORDINATEN (PHIS, LAMS) IMC** ROTIERTEN SYSTEM. DER NORDPOL DIESES SYSTEMS HATC** DIE WAHREN KOORDINATEN (POLPHI, POLLAM)C** VERSIONS-C** DATUM : 03.05.90C**C** EXTERNALS: KEINEC** EINGABE-C** PARAMETER: PHI REAL BREITE DES PUNKTES IM GEOGR. SYSTEMC** LAM REAL LAENGE DES PUNKTES IM GEOGR. SYSTEMC** POLPHI REAL GEOGR.BREITE DES N-POLS DES ROT. SYSTEMSC** POLLAM REAL GEOGR.LAENGE DES N-POLS DES ROT. SYSTEMSC** AUSGABE-C** PARAMETER: ROTIERTE BREITE PHIS ALS WERT DER FUNKTIONC** ALLE WINKEL IN GRAD (NORDEN>0, OSTEN>0)C**C** COMMON-C** BLOECKE : KEINEC**C** FEHLERBE-C** HANDLUNG : KEINEC** VERFASSER: G. DE MORSIERREAL LAM,PHI,POLPHI,POLLAMDATA ZRPI18 , ZPIR18 / 57.2957795 , 0.0174532925 /ZSINPOL = SIN(ZPIR18*POLPHI)ZCOSPOL = COS(ZPIR18*POLPHI)ZLAMPOL = ZPIR18*POLLAMZPHI = ZPIR18*PHIZLAM = LAMIF(ZLAM.GT.180.0) ZLAM = ZLAM - 360.0ZLAM = ZPIR18*ZLAMZARG = ZCOSPOL*COS(ZPHI)*COS(ZLAM-ZLAMPOL) + ZSINPOL*SIN(ZPHI)PHTOPHS = ZRPI18*ASIN(ZARG)RETURNENDc ---------------------------------------------------------c Spherical distance between two lat/lon pointsc ---------------------------------------------------------real function sdis(xp,yp,xq,yq)cc calculates spherical distance (in km) between two points givenc by their spherical coordinates (xp,yp) and (xq,yq), respectively.creal reparameter (re=6370.)real xp,yp,xq,yq,argarg=sind(yp)*sind(yq)+cosd(yp)*cosd(yq)*cosd(xp-xq)if (arg.lt.-1.) arg=-1.if (arg.gt.1.) arg=1.sdis=re*acos(arg)endc ********************************************************************************c * NETCDF INPUT/OUTPUT *c ********************************************************************************c ---------------------------------------------------------c Subroutines to write the netcdf output filec ---------------------------------------------------------subroutine writecdf2D(cdfname,cstname,> varname,arr,ctime,> dx,dy,xmin,ymin,nx,ny,> crefile,crevar)c Create and write to the netcdf file <cdfname>. The variablec with name <varname> and with time <time> is written. The datac are in the two-dimensional array <arr>. The list <dx,dy,xmin,c ymin,nx,ny> specifies the output grid. The flags <crefile> andc <crevar> determine whether the file and/or the variable shouldc be created. 1: create / 0: not createdIMPLICIT NONEc Declaration of input parameterscharacter*80 cdfname,cstname,varnameinteger nx,nyreal arr(nx,ny)real dx,dy,xmin,ymininteger ctimeinteger crefile,crevarc Further variablesreal varmin(4),varmax(4),stag(4)integer ierr,cdfid,ndim,vardim(4)real mdvinteger datar(14),stdate(5)integer ireal timeC Definitionsvarmin(1)=xminvarmin(2)=yminvarmin(3)=1050.varmax(1)=xmin+real(nx-1)*dxvarmax(2)=ymin+real(ny-1)*dyvarmax(3)=1050.ndim=4vardim(1)=nxvardim(2)=nyvardim(3)=1stag(1)=0.stag(2)=0.stag(3)=0.mdv=-999.98999time=real(ctime)C Create the fileif (crefile.eq.0) thencall cdfwopn(cdfname,cdfid,ierr)if (ierr.ne.0) goto 906else if (crefile.eq.1) thencall crecdf(cdfname,cdfid,> varmin,varmax,ndim,cstname,ierr)if (ierr.ne.0) goto 903C Write the constants filedatar(1)=vardim(1)datar(2)=vardim(2)datar(3)=int(1000.*varmax(2))datar(4)=int(1000.*varmin(1))datar(5)=int(1000.*varmin(2))datar(6)=int(1000.*varmax(1))datar(7)=int(1000.*dx)datar(8)=int(1000.*dy)datar(9)=1datar(10)=1datar(11)=0 ! data versiondatar(12)=0 ! cstfile versiondatar(13)=0 ! longitude of poledatar(14)=90000 ! latitude of poledo i=1,5stdate(i)=0enddocall wricst(cstname,datar,0.,0.,0.,0.,stdate)endifc Write the data to the netcdf file, and close the fileif (crevar.eq.1) thencall putdef(cdfid,varname,ndim,mdv,> vardim,varmin,varmax,stag,ierr)if (ierr.ne.0) goto 904endifcall putdat(cdfid,varname,time,0,arr,ierr)if (ierr.ne.0) goto 905call clscdf(cdfid,ierr)returnc Error handling903 print*,'*** Problem to create netcdf file ***'stop904 print*,'*** Problem to write definition ***'stop905 print*,'*** Problem to write data ***'stop906 print*,'*** Problem to open netcdf file ***'stopENDc ----------------------------------------------------------------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