Blame | Last modification | View Log | Download | RSS feed
PROGRAM pv_to_qgpvc ********************************************************************************c * TRANSFORM ERTEL'S PV TO QUASI-GEOSTROPHIC PV *c * Rene Fehlmann 1994 / Code re-organization: Michael Sprenger, 2006 *c ********************************************************************************c --------------------------------------------------------------------------------c Declaration of variables, parameters, externals and common blocksc --------------------------------------------------------------------------------implicit nonec Input and output filecharacter*80 pvsrcfilecharacter*80 referfilecharacter*80 anomafilec Grid parametersinteger nx,ny,nzreal xmin,ymin,zmin,xmax,ymax,zmaxreal dx,dy,dzreal mdvc Numerical and physical parametersreal pi180 ! Pi/180parameter (pi180=3.141592654/180.)real rerd ! Earth's radiusparameter (rerd=6.371229e6)real eps ! Numerical epsilonparameter (eps=0.01)real scale ! Scale for PV unitparameter (scale=1e6)real minagl ! No PV and qgPV below this height AGLparameter (minagl=1000.)c Reference state and grid parametersreal, allocatable,dimension (:) :: nsqrefreal, allocatable,dimension (:) :: thetarefreal, allocatable,dimension (:) :: rhorefreal, allocatable,dimension (:) :: pressrefreal, allocatable,dimension (:) :: zrefreal, allocatable,dimension (:,:) :: coriolreal, allocatable,dimension (:,:) :: ororeal deltax,deltay,deltazc 3d fields for calculation of qgPV and Ertel's PVreal,allocatable,dimension (:,:,:) :: qgpv,pv1,pv2,pvc Auxiliary variablesreal zposinteger i,j,kinteger statcharacter*80 varnameinteger istepreal mean,rmsq,min,maxinteger stepreal,allocatable,dimension (:,:) :: tmpc --------------------------------------------------------------------------------c Inputc --------------------------------------------------------------------------------print*,'********************************************************'print*,'* PV_TO_QGPV *'print*,'********************************************************'c Read parameter fileopen(10,file='fort.10')read(10,*) pvsrcfileread(10,*) referfileread(10,*) anomafileclose(10)print*print*,trim(pvsrcfile)print*,trim(referfile)print*,trim(anomafile)print*c Get lat/lon gid parameters from input filecall read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,> pvsrcfile)print*,'Read_Dim: nx,ny,nz = ',nx,ny,nzprint*,' dx,dy,dz = ',dx,dy,dzprint*,' xmin,ymin,zmin = ',xmin,ymin,zminprint*,' mdv = ',mdvprint*c Count from 0, not from 1: consistent with <inv_cart.f>.nx=nx-1ny=ny-1nz=nz-1c Allocate memory for reference profile and grid parametersallocate(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(coriol (0:nx,0:ny),STAT=stat)if (stat.ne.0) print*,'error allocating coriol'allocate(oro (0:nx,0:ny),STAT=stat)if (stat.ne.0) print*,'error allocating oro'c Allocate memory for calculation of qgPV and Ertel's PVallocate(pv1 (0:nx,0:ny,0:nz),STAT=stat)if (stat.ne.0) print*,'error allocating pv1'allocate(pv2 (0:nx,0:ny,0:nz),STAT=stat)if (stat.ne.0) print*,'error allocating pv2'allocate(pv (0:nx,0:ny,0:nz),STAT=stat)if (stat.ne.0) print*,'error allocating pv'allocate(qgpv(0:nx,0:ny,0:nz),STAT=stat)if (stat.ne.0) print*,'error allocating qgpv'c Allocate memory for temporary arrayallocate(tmp(0:nx,0:ny),STAT=stat)if (stat.ne.0) print*,'error allocating tmp'c --------------------------------------------------------------------------------c Calculate the qgPV from Ertel's PV and put it onto filec --------------------------------------------------------------------------------c Read data from filevarname='PV'call read_inp (pv1,varname,pvsrcfile,> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)varname='PV_AIM'call read_inp (pv2,varname,pvsrcfile,> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)c Read reference profile and grid parameterscall read_ref (nsqref,rhoref,thetaref,pressref,zref,> nx,ny,nz,deltax,deltay,deltaz,coriol,oro,> referfile)c If the PV is negative, set it to zerodo i=0,nxdo j=0,nydo k=0,nzif (pv1(i,j,k).lt.0.) pv1(i,j,k)=0.if (pv2(i,j,k).lt.0.) pv2(i,j,k)=0.enddoenddoenddoc Get the difference of Ertel's PV and set all missing values to 0do i=0,nxdo j=0,nydo k=0,nzif ((abs(pv1(i,j,k)-mdv).gt.eps).and.> (abs(pv2(i,j,k)-mdv).gt.eps)) thenpv(i,j,k)=pv1(i,j,k)-pv2(i,j,k)elsepv(i,j,k)=0.endifenddoenddoenddoc Calculate qgPVcall epv_to_qgpv (qgpv,pv,> rhoref,pressref,nsqref,thetaref,> nx,ny,nz,mdv)c Set values on the boundaries to zerodo i=0,nxdo j=0,nyqgpv(i,j, 0)=0.qgpv(i,j,nz)=0.enddoenddodo i=0,nxdo k=0,nzqgpv(i, 0,k)=0.qgpv(i,ny,k)=0.enddoenddodo j=0,nydo k=0,nzqgpv( 0,j,k)=0.qgpv(nx,j,k)=0.enddoenddoc Set all values to zero which are too near to the surfacedo i=0,nxdo j=0,nydo k=0,nzzpos=zmin+real(k)*dzif (zpos.lt.(oro(i,j)+minagl)) thenpv(i,j,k)=0.qgpv(i,j,k)=0.endifenddoenddoenddoc Write result to netcdf filevarname='QGPV'call write_inp (qgpv,varname,anomafile,nx,ny,nz)varname='PV'call write_inp (pv,varname,anomafile,nx,ny,nz)c Write some infoprint*print*,'PV -> qgPV: k z min max mean rmsq'step=nz/10if (step.lt.1) step=1do k=0,nz,stepdo i=0,nxdo j=0,nytmp(i,j)=qgpv(i,j,k)enddoenddocall calc_error(min,max,mean,rmsq,tmp,nx,ny)write(*,'(8x,i3,f10.1,4f10.2)')> k,zmin+real(k)*dz,scale*min,scale*max,> scale*mean,scale*rmsqenddoprint*c --------------------------------------------------------------------------------c Format specificationsc --------------------------------------------------------------------------------111 format (5f20.9)106 format (2f20.9)endc ********************************************************************************c * NETCDF INPUT AND OUTPUT *c ********************************************************************************c --------------------------------------------------------------------------------c Write input field to netcdfc --------------------------------------------------------------------------------SUBROUTINE write_inp (field,fieldname,pvsrcfile,nx,ny,nz)c Read <fieldname> from netcdf file <pvsrcfile> into <field>. The grid is specifiedc by <nx,ny,nz,dx,dy,dz,xmin,ymin,zmin>. A check is performed whether the inputc files are consitent with this grid.implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal field (0:nx,0:ny,0:nz)character*80 fieldnamecharacter*80 pvsrcfilec Auxiliary variablesinteger cdfid,statinteger vardim(4)real misdatreal varmin(4),varmax(4),stag(4)integer ndimin,outid,i,j,kreal tmp(0:nx,0:ny,0:nz)integer ntimesreal time(200)integer nvarscharacter*80 vnam(100),varnameinteger isokc Get grid parameters from PVcall cdfopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 998call getvars(cdfid,nvars,vnam,stat)if (stat.ne.0) goto 998isok=0varname='PV'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 998call getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 998time(1)=0.call gettimes(cdfid,time,ntimes,stat)if (stat.ne.0) goto 998call clscdf(cdfid,stat)if (stat.ne.0) goto 998c Save variables (write definition, if necessary)call cdfwopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 998isok=0varname=fieldnamecall check_varok(isok,varname,vnam,nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 998endifcall putdat(cdfid,varname,time(1),0,field,stat)print*,'W ',trim(varname),' ',trim(pvsrcfile)if (stat.ne.0) goto 998c Close input netcdf filecall clscdf(cdfid,stat)if (stat.ne.0) goto 998returnc Exception handling998 print*,'Write_Inp: Problem with input netcdf file... Stop'stopendc --------------------------------------------------------------------------------c Read input fields for reference profilec --------------------------------------------------------------------------------SUBROUTINE read_inp (field,fieldname,pvsrcfile,> nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)c Read <fieldname> from netcdf file <pvsrcfile> into <field>. The grid is specifiedc by <nx,ny,nz,dx,dy,dz,xmin,ymin,zmin>. A check is performed whether the inputc files are consitent with this grid. The missing data value is set to <mdv>.implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal field(0:nx,0:ny,0:nz)character*80 fieldnamecharacter*80 pvsrcfilereal dx,dy,dz,xmin,ymin,zminreal mdvc Numerical and physical parametersreal epsparameter (eps=0.01)c Auxiliary variablesinteger cdfid,stat,cdfid99integer vardim(4)real misdatreal varmin(4),varmax(4),stag(4)integer ndimin,outid,i,j,kreal tmp(nx,ny,nz)integer ntimesreal time(200)integer nvarscharacter*80 vnam(100),varnameinteger isokc Open the input netcdf filecall cdfopn(pvsrcfile,cdfid,stat)if (stat.ne.0) goto 998c Check whether needed variables are on filecall getvars(cdfid,nvars,vnam,stat)if (stat.ne.0) goto 998isok=0varname=trim(fieldname)call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 998c Get the grid parameters from thetacall getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 998time(1)=0.call gettimes(cdfid,time,ntimes,stat)if (stat.ne.0) goto 998c Check whether grid parameters are consistentif ( (vardim(1).ne.(nx+1)).or.> (vardim(2).ne.(ny+1)).or.> (vardim(3).ne.(nz+1)).or.> (abs(varmin(1)-xmin).gt.eps).or.> (abs(varmin(2)-ymin).gt.eps).or.> (abs(varmin(3)-zmin).gt.eps).or.> (abs((varmax(1)-varmin(1))/real(vardim(1)-1)-dx).gt.eps).or.> (abs((varmax(2)-varmin(2))/real(vardim(2)-1)-dy).gt.eps).or.> (abs((varmax(3)-varmin(3))/real(vardim(3)-1)-dz).gt.eps) )>thenprint*,'Input grid inconsitency...'print*,' Nx = ',vardim(1),nx+1print*,' Ny = ',vardim(2),ny+1print*,' Nz = ',vardim(3),nz+1print*,' Varminx = ',varmin(1),xminprint*,' Varminy = ',varmin(2),yminprint*,' Varminz = ',varmin(3),zminprint*,' Dx = ',(varmax(1)-varmin(1))/real(nx-1),dxprint*,' Dy = ',(varmax(2)-varmin(2))/real(ny-1),dyprint*,' Dz = ',(varmax(3)-varmin(3))/real(nz-1),dzgoto 998endifc Load variablescall getdef(cdfid,varname,ndimin,misdat,vardim,> varmin,varmax,stag,stat)if (stat.ne.0) goto 998call getdat(cdfid,varname,time(1),0,field,stat)print*, 'R ',trim(varname),' ',trim(pvsrcfile)if (stat.ne.0) goto 998c Close input netcdf filecall clscdf(cdfid,stat)if (stat.ne.0) goto 998c Set missing data value to <mdv>do i=1,nxdo j=1,nydo k=1,nzif (abs(field(i,j,k)-misdat).lt.eps) thenfield(i,j,k)=mdvendifenddoenddoenddoreturnc Exception handling998 print*,'Read_Inp: Problem with input netcdf file... Stop'stopendc --------------------------------------------------------------------------------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'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)>. If this isC the case, <isok> is incremented by 1. Otherwise <isok> 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 Get grid parametersc --------------------------------------------------------------------------------subroutine read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,> pvsrcfile)c Get the grid parameters from the variable <THETA> on the input file <pvsrcfile>.c The grid parameters arec nx,ny,nz : Number of grid points in x, y and z directionc xmin,ymin,zmin : Minimum domain coordinates in x, y and z directionc xmax,ymax,zmax : Maximal domain coordinates in x, y and z directionc dx,dy,dz : Horizontal and vertical resolutionc Additionally, it is checked whether the vertical grid is equally spaced. If ok,c the grid paramters are transformed from lon/lat to distance (in meters)implicit nonec Declaration of subroutine parameterscharacter*80 pvsrcfileinteger nx,ny,nzreal dx,dy,dzreal xmin,ymin,zmin,xmax,ymax,zmaxreal mdvc Numerical epsilon and other physical/geoemtrical parametersreal epsparameter (eps=0.01)c Auxiliary variablesinteger cdfid,cstidinteger ierrcharacter*80 vnam(100),varnameinteger nvarsinteger isokinteger vardim(4)real misdatreal varmin(4),varmax(4),stag(4)real aklev(1000),bklev(1000),aklay(1000),bklay(1000)real dhcharacter*80 csninteger ndiminteger ic Get all grid parameterscall cdfopn(pvsrcfile,cdfid,ierr)if (ierr.ne.0) goto 998call getvars(cdfid,nvars,vnam,ierr)if (ierr.ne.0) goto 998isok=0varname='PV'call check_varok(isok,varname,vnam,nvars)if (isok.eq.0) goto 998call getcfn(cdfid,csn,ierr)if (ierr.ne.0) goto 998call cdfopn(csn,cstid,ierr)if (ierr.ne.0) goto 998call getdef(cdfid,varname,ndim,misdat,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)zmin=varmin(3)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=varmax(1)ymax=varmax(2)zmax=varmax(3)dz=(zmax-zmin)/real(nz-1)call clscdf(cstid,ierr)if (ierr.ne.0) goto 998call clscdf(cdfid,ierr)if (ierr.ne.0) goto 998c Check whether the grid is equallay spaced in the verticaldo i=1,nz-1dh=aklev(i+1)-aklev(i)if (abs(dh-dz).gt.eps) thenprint*,'Aklev: Vertical grid must be equally spaced... Stop'print*,(aklev(i),i=1,nz)stopendifdh=aklay(i+1)-aklay(i)if (abs(dh-dz).gt.eps) thenprint*,'Aklay: Vertical grid must be equally spaced... Stop'print*,(aklay(i),i=1,nz)stopendifenddoc Set missing data valuemdv=misdatreturnc Exception handling998 print*,'Read_Dim: Problem with input netcdf file... Stop'stopendc ********************************************************************************c * CALCULATION *c ********************************************************************************c --------------------------------------------------------------------------------c Calculate qgPV from Ertels's PVc --------------------------------------------------------------------------------subroutine epv_to_qgpv (qgpv,pv,> rhoref,pressref,nsqref,thetaref,> nx,ny,nz,mdv)c Calculate the qgPV from Ertel's PV according to equation 2.11 p16, Thesisc from Rene Fehlmann.implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal qgpv(0:nx,0:ny,0:nz),pv(0:nx,0:ny,0:nz)real rhoref (0:2*nz)real nsqref (0:2*nz)real thetaref(0:2*nz)real pressref(0:2*nz)real mdvc Numerical epsilonreal gparameter (g=9.81)real epsparameter (eps=0.01)real scaleparameter (scale=1e6)c Auxiliary variablesinteger i,j,kinteger kkc Calculationdo i=0,nxdo j=0,nydo k=0,nzkk=2*kif (( abs(rhoref(kk) -mdv).gt.eps).and.> ( abs(thetaref(kk)-mdv).gt.eps).and.> ( abs(nsqref(kk) -mdv).gt.eps).and.> ( abs(pv(i,j,k) -mdv).gt.eps)) thenqgpv(i,j,k)=rhoref(kk)*g*pv(i,j,k)/thetaref(kk)/> nsqref(kk)/scaleelseqgpv(i,j,k)=0.endifenddoenddoenddoendc --------------------------------------------------------------------------------c Calculate error statisticsc --------------------------------------------------------------------------------subroutine calc_error (min,max,mean,rmsq,tmp,nx,ny)c Calculate the error statistics for the two-dimensional error field <tmp>. Thec following error measures are calculated: the minimum <min>, the maximum <max>,c the mean <mean>, the root-mean square <rmsq>implicit nonec Declaration of subroutine parametersinteger nx,nyreal tmp(0:nx,0:ny)real mean,rmsqreal min,maxc Auxiliary variablesinteger i,jreal suminteger cntc Calculate the minimum and maximummin=tmp(0,0)max=tmp(0,0)do i=0,nxdo j=0,nyif (tmp(i,j).lt.min) min=tmp(i,j)if (tmp(i,j).gt.max) max=tmp(i,j)enddoenddoc Calculate the meansum=0.cnt=0do i=0,nxdo j=0,nycnt=cnt+1sum=sum+tmp(i,j)enddoenddoif (cnt.ge.1) thenmean=sum/real(cnt)elsemean=0.endifc Calculate rmsqrmsq=0.cnt=0do i=0,nxdo j=0,nycnt=cnt+1rmsq=rmsq+(tmp(i,j)-mean)**2enddoenddoif (cnt.ge.1) thenrmsq=1./real(cnt)*sqrt(rmsq)elsermsq=0.endifend