Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed
PROGRAM rotate_gridc *******************************************************************c * Rotate to a grid with the PV anomaly at its center *c * Michael Sprenger / Autumn 2006 *c *******************************************************************implicit nonec -------------------------------------------------------------------c Declaration of parameters and variablesc -------------------------------------------------------------------c Specification of input parametersreal clon,clat,rotationinteger rnx,rnyreal rdx,rdyinteger 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_grid *'print*,'*********************************************************'c Read parameter fileopen(10,file='fort.10')read(10,*) in_cfnread(10,*) out_cfnread(10,*) name,rnxif ( trim(name).ne.'ROT_NX') stopread(10,*) name,rnyif ( trim(name).ne.'ROT_NY') stopread(10,*) name,rdxif ( trim(name).ne.'ROT_DX') stopread(10,*) name,rdyif ( trim(name).ne.'ROT_DY') 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*,rnx,rny,rdx,rdyprint*,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) = rnxout_vardim(2) = rnyout_vardim(3) = in_nzout_varmin(1) = -real(rnx/2)*rdxout_varmin(2) = -real(rny/2)*rdyout_varmin(3) = in_varmin(3)out_varmax(1) = real(rnx/2)*rdxout_varmax(2) = real(rny/2)*rdyout_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 = rdxout_dy = rdyout_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 = clonout_pollat = clatdo 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 filedatar(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='LAT'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='LON'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 Coriolis parametervarname='CORIOL'print*,'Rotating scalar : ',trim(varname)do i=1,in_nxdo j=1,in_nylat=in_ymin+real(j-1)*in_dyin_field3(i,j,1)=2.*omegaerd*sin(lat*degrad)enddoenddocall getenvir (clon,clat,rotation,0,> in_field3,in_dx,in_dy,> in_xmin,in_ymin,in_nx,in_ny,1,in_mdv,> out_coriol,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_coriol,ierr)if (ierr.ne.0) goto 997c X coordinatevarname='X'print*,'Getting X grid : ',trim(varname)do j=1,out_nyout_x(out_nx/2,j)=0.do i=out_nx/2+1,out_nxout_x(i,j)=out_x(i-1,j)+> sdis(out_lon(i-1,j),out_lat(i-1,j),> out_lon(i ,j),out_lat(i ,j))enddodo i=out_nx/2-1,1,-1out_x(i,j)=out_x(i+1,j)-> sdis(out_lon(i+1,j),out_lat(i+1,j),> out_lon(i ,j),out_lat(i ,j))enddoenddoout_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_x,ierr)if (ierr.ne.0) goto 997c Y coordinatevarname='Y'print*,'Getting Y grid : ',trim(varname)do i=1,out_nxout_y(i,out_ny/2)=0.do j=out_ny/2+1,out_nyout_y(i,j)=out_y(i,j-1)+> sdis(out_lon(i,j-1),out_lat(i,j-1),> out_lon(i ,j),out_lat(i ,j))enddodo j=out_ny/2-1,1,-1out_y(i,j)=out_y(i,j+1)-> sdis(out_lon(i,j+1),out_lat(i,j+1),> out_lon(i ,j),out_lat(i ,j))enddoenddoout_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_y,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 lat/lon grid'stop997 print*,'Z: Problems with output to rotated grid'stopendc ********************************************************************************c * SUBROUTINE: ROTATION TO LOCAL CARTESIAN COORDINATE SYSTEM *c ********************************************************************************c --------------------------------------------------------------------------------c Subroutine to get environment (vector+scalar)c --------------------------------------------------------------------------------SUBROUTINE getenvir (clon,clat,rotation,rotmode,> inar, dx, dy, xmin, ymin, nx, ny, nz,mdv,> outar,rdx,rdy,rxmin,rymin,rnx,rny,rnz)c Get an input field <inar> and the center <clon,clat> of a structure. The inputc array is defined on a lat/lon grid with grid specification <dx,dy,xmin,ymin,nx,ny>.c The input field is then rotated to an output grid <rdx,rdy,rxmin,rymin,rnx,rny>,c whereby the structure <clon,clat> is at the center of the new grid and the outputc grid is rotated with rotation angle <rotation>. This routine rotates the componentsc of a vector field for <rotmode=1|2>: <rotmode=1> refers to the x xomponent of thec field, <rotmode=2> to the y component. If <rotmode=0>, scalar field is assumed.implicit nonec Declaration of input parametersinteger nx,ny,nzreal dx,dy,xmin,yminreal inar(nx,ny,nz)real clon,clat,rotationreal mdvinteger rotmodec Declaration of output parametersinteger rnx,rny,rnzreal rdx,rdy,rxmin,ryminreal outar(rnx,rny,rnz)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 rlon1(rnx,rny),rlat1(rnx,rny)real rlon2(rnx,rny),rlat2(rnx,rny)real lon(rnx,rny),lat(rnx,rny)real rotangle1(rnx,rny),rotangle2(rnx,rny)real rotangle(rnx,rny)real sinoutar(rnx,rny,rnz),cosoutar(rnx,rny,rnz)real xmax,ymaxreal 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,frac1jreal lonmean,latmeancharacter*80 cdfname,varname,cstnamereal vx1,vx2,vy1,vy2,angle,vx2mininteger sc Externalsreal lmstolm,phstophexternal lmstolm,phstophc Get rotated coordinatesdo i=1,rnxdo j=1,rnyrlon1(i,j)=rxmin+real(i-1)*rdxrlat1(i,j)=rymin+real(j-1)*rdyenddoenddoc First coordinate transformation (make the local coordinate system parallel to equator)pollon=-180.pollat=90.+rotationdo i=1,rnxdo j=1,rnyrlon2(i,j)=90.+lmstolm(rlat1(i,j),rlon1(i,j)-90.,pollat,pollon)rlat2(i,j)=phstoph(rlat1(i,j),rlon1(i,j)-90.,pollat,pollon)enddoenddoc Second coordinate transformation (make the local coordinate system parallel to equator)pollon=clon-180.if (pollon.lt.-180.) pollon=pollon+360.pollat=90.-clatdo i=1,rnxdo j=1,rnylon(i,j)=lmstolm(rlat2(i,j),rlon2(i,j),pollat,pollon)lat(i,j)=phstoph(rlat2(i,j),rlon2(i,j),pollat,pollon)enddoenddoc Get the angle between the rotated and non-rotated coordinate frameif ((rotmode.eq.1).or.(rotmode.eq.2)) thendo i=2,rnx-1do j=2,rny-1c Angle between latitude circlesvx1=1.vy1=0.vx2min=(lon(i+1,j)-lon(i-1,j))*cos(pi180*lat(i,j))do s=-1,1,2vx2=(lon(i+1,j)-lon(i-1,j)+real(s)*360.)*> cos(pi180*lat(i,j))if (abs(vx2).lt.abs(vx2min)) vx2min=vx2enddovx2=vx2minvy2=lat(i+1,j)-lat(i-1,j)call getangle(vx1,vy1,vx2,vy2,angle)rotangle1(i,j)=anglec Angle between longitude circlesvx1=0.vy1=1.vx2min=(lon(i,j+1)-lon(i,j-1))*cos(pi180*lat(i,j))do s=-1,1,2vx2=(lon(i+1,j)-lon(i-1,j)+real(s)*360.)*> cos(pi180*lat(i,j))if (abs(vx2).lt.abs(vx2min)) vx2min=vx2enddovx2=vx2minvy2=lat(i,j+1)-lat(i,j-1)call getangle(vx1,vy1,vx2,vy2,angle)rotangle2(i,j)=angleenddoenddoc Set the angle at the boundariesdo i=1,rnxrotangle1(i,rny)=2.0*rotangle1(i,rny-1)-rotangle1(i,rny-2)rotangle1(i,1) =2.0*rotangle1(i,2)-rotangle1(i,3)rotangle2(i,rny)=2.0*rotangle2(i,rny-1)-rotangle2(i,rny-2)rotangle2(i,1) =2.0*rotangle2(i,2)-rotangle2(i,3)enddodo j=1,rnyrotangle1(rnx,j)=2.0*rotangle1(rnx-1,j)-rotangle1(rnx-2,j)rotangle1(1,j) =2.0*rotangle1(2,j)-rotangle1(3,j)rotangle2(rnx,j)=2.0*rotangle2(rnx-1,j)-rotangle2(rnx-2,j)rotangle2(1,j) =2.0*rotangle2(2,j)-rotangle2(3,j)enddoc Set the final rotation angledo i=1,rnxdo j=1,rnyrotangle(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,rnxdo j=1,rny100 if (lon(i,j).lt.xmin) thenlon(i,j)=lon(i,j)+360.goto 100endif102 if (lon(i,j).gt.(xmin+real(nx-1)*dx)) thenlon(i,j)=lon(i,j)-360.goto 102endifenddoenddoc Rotate the scalar or the vector componentdo i=1,rnxdo j=1,rnydo k=1,rnzc Get indexrindx=(lon(i,j)-xmin)/dx+1.rindy=(lat(i,j)-ymin)/dy+1.indx=int(rindx)indy=int(rindy)if ((indx.lt.1).or.(indx.gt.nx).or.> (indy.lt.1).or.(indy.gt.ny)) thenprint*,'lat/lon interpolation not possible....'print*,i,j,k,indx,indy,lon(i,j),lat(i,j)stopendifc Get inidices of left and upper neighboursindr=indx+1if (indr.gt.nx) indr=1indu=indy+1if (indu.gt.ny) 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)=outvalenddoenddoenddoc Get components for testsif (test.eq.1) thendo i=1,rnxdo j=1,rnydo k=1,rnzcosoutar(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,rnxdo j=1,rnydo k=1,rnzif ( 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='RLON2'call writecdf2D(cdfname,cstname,> varname,rlon2,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='RLAT2'call writecdf2D(cdfname,cstname,> varname,rlat2,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 LMSTOLM (PHIS, LAMS, POLPHI, POLLAM)CC**** LMSTOLM - FC:BERECHNUNG DER WAHREN GEOGRAPHISCHEN LAENGE FUERC**** EINEN PUNKT MIT DEN KOORDINATEN (PHIS, LAMS)C**** IM ROTIERTEN SYSTEM. DER NORDPOL DES SYSTEMS HATC**** DIE WAHREN KOORDINATEN (POLPHI, POLLAM)C** AUFRUF : LAM = LMSTOLM (PHIS, LAMS, POLPHI, POLLAM)C** ENTRIES : KEINEC** ZWECK : BERECHNUNG DER WAHREN GEOGRAPHISCHEN LAENGE FUERC** EINEN PUNKT MIT DEN KOORDINATEN (PHIS, LAMS)C** IM 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: PHIS REAL GEOGR. BREITE DES PUNKTES IM ROT.SYS.C** LAMS REAL GEOGR. LAENGE DES PUNKTES IM ROT.SYS.C** POLPHI REAL WAHRE GEOGR. BREITE DES NORDPOLSC** POLLAM REAL WAHRE GEOGR. LAENGE DES NORDPOLSC** 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: D.MAJEWSKIREAL LAMS,PHIS,POLPHI,POLLAMDATA ZRPI18 , ZPIR18 / 57.2957795 , 0.0174532925 /ZSINPOL = SIN(ZPIR18*POLPHI)ZCOSPOL = COS(ZPIR18*POLPHI)ZLAMPOL = ZPIR18*POLLAMZPHIS = ZPIR18*PHISZLAMS = LAMSIF(ZLAMS.GT.180.0) ZLAMS = ZLAMS - 360.0ZLAMS = ZPIR18*ZLAMSZARG1 = SIN(ZLAMPOL)*(- ZSINPOL*COS(ZLAMS)*COS(ZPHIS) +1 ZCOSPOL* SIN(ZPHIS)) -2 COS(ZLAMPOL)* SIN(ZLAMS)*COS(ZPHIS)ZARG2 = COS(ZLAMPOL)*(- ZSINPOL*COS(ZLAMS)*COS(ZPHIS) +1 ZCOSPOL* SIN(ZPHIS)) +2 SIN(ZLAMPOL)* SIN(ZLAMS)*COS(ZPHIS)IF (ABS(ZARG2).LT.1.E-30) THENIF (ABS(ZARG1).LT.1.E-30) THENLMSTOLM = 0.0ELSEIF (ZARG1.GT.0.) THENLMSTOLAM = 90.0ELSELMSTOLAM = -90.0ENDIFELSELMSTOLM = ZRPI18*ATAN2(ZARG1,ZARG2)ENDIFRETURNENDREAL FUNCTION PHSTOPH (PHIS, LAMS, POLPHI, POLLAM)CC**** PHSTOPH - FC:BERECHNUNG DER WAHREN GEOGRAPHISCHEN BREITE FUERC**** EINEN PUNKT MIT DEN KOORDINATEN (PHIS, LAMS) IMC**** ROTIERTEN SYSTEM. DER NORDPOL DIESES SYSTEMS HATC**** DIE WAHREN KOORDINATEN (POLPHI, POLLAM)C** AUFRUF : PHI = PHSTOPH (PHIS, LAMS, POLPHI, POLLAM)C** ENTRIES : KEINEC** ZWECK : BERECHNUNG DER WAHREN GEOGRAPHISCHEN BREITE FUERC** EINEN 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: PHIS REAL GEOGR. BREITE DES PUNKTES IM ROT.SYS.C** LAMS REAL GEOGR. LAENGE DES PUNKTES IM ROT.SYS.C** POLPHI REAL WAHRE GEOGR. BREITE DES NORDPOLSC** POLLAM REAL WAHRE GEOGR. LAENGE DES NORDPOLSC** AUSGABE-C** PARAMETER: WAHRE GEOGRAPHISCHE BREITE ALS WERT DER FUNKTIONC** ALLE WINKEL IN GRAD (NORDEN>0, OSTEN>0)C**C** COMMON-C** BLOECKE : KEINEC**C** FEHLERBE-C** HANDLUNG : KEINEC** VERFASSER: D.MAJEWSKIREAL LAMS,PHIS,POLPHI,POLLAMDATA ZRPI18 , ZPIR18 / 57.2957795 , 0.0174532925 /SINPOL = SIN(ZPIR18*POLPHI)COSPOL = COS(ZPIR18*POLPHI)ZPHIS = ZPIR18*PHISZLAMS = LAMSIF(ZLAMS.GT.180.0) ZLAMS = ZLAMS - 360.0ZLAMS = ZPIR18*ZLAMSARG = COSPOL*COS(ZPHIS)*COS(ZLAMS) + SINPOL*SIN(ZPHIS)PHSTOPH = ZRPI18*ASIN(ARG)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