Blame | Last modification | View Log | Download | RSS feed
PROGRAM add2pc *********************************************************************c * Add output from the PV inversion to the original P file *c * Zonal wind (U), meridional wind (V) and temperature (T) are *c * modified. All other fields are not affected by the programme *c * *c * Michael Sprenger / Summer, Autumn 2006c *********************************************************************implicit nonec ---------------------------------------------------------------------c Declaration of parameters and variablesc ---------------------------------------------------------------------c Input parameterscharacter*80 ml_fncharacter*80 zm_fncharacter*80 or_fnreal transxyc Variables for input P file : model levelreal 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_idate(5)integer ml_nvarscharacter*80 ml_vnam(80)real,allocatable, dimension (:,:) :: ml_ps,ml_ororeal,allocatable, dimension (:,:,:) :: ml_t3,ml_u3,ml_v3,ml_z3real,allocatable, dimension (:,:,:) :: ml_p3,ml_tv3,ml_q3,ml_p0integer,allocatable, dimension (:,:,:) :: flag_mlc Variables for GEO.MODreal zm_varmin(4),zm_varmax(4),zm_stag(4)integer zm_vardim(4)real zm_mdvinteger zm_ndiminteger zm_nx,zm_ny,zm_nzreal zm_xmin,zm_xmax,zm_ymin,zm_ymax,zm_dx,zm_dyinteger zm_ntimesreal zm_aklev(500),zm_bklev(500)real zm_aklay(500),zm_bklay(500)real zm_timereal zm_pollon,zm_pollatinteger zm_idate(5)integer zm_nvarscharacter*80 zm_vnam(80)real,allocatable, dimension (:,:,:) :: zm_u3,zm_v3,zm_t3,zm_z3real,allocatable, dimension (:,:,:) :: zm_p3real,allocatable, dimension (:,:) :: zm_rlat,zm_rloninteger,allocatable, dimension (:,:,:) :: flag_zmc Variables for GEO.ORGreal or_varmin(4),or_varmax(4),or_stag(4)integer or_vardim(4)real or_mdvinteger or_ndiminteger or_nx,or_ny,or_nzreal or_xmin,or_xmax,or_ymin,or_ymax,or_dx,or_dyinteger or_ntimesreal or_timereal or_pollon,or_pollatinteger or_idate(5)integer or_nvarscharacter*80 or_vnam(80)real,allocatable, dimension (:,:,:) :: or_p3real,allocatable, dimension (:,:,:) :: or_u3,or_v3,or_t3c Anomaliesreal,allocatable, dimension (:,:,:) :: an_p3,an_u3,an_v3,an_t3c Array with the weighting functionreal,allocatable, dimension (:,:) :: weight,distc Flag for test modeinteger testparameter (test=1)c Flag for Poisson fillinginteger poissonparameter (poisson=1)c Physical and numerical parametersreal eps ! Numerical epsilonparameter (eps=0.001)real dpextra ! Allowed range for extrapolation (% of pressure)parameter (dpextra=0.1)real g ! Earth's gravityparameter (g=9.80665)real tzero ! Conversion Celius/Kelvinparameter (tzero=273.15)real kappa ! Kappa (Definition of potential temperature)parameter (kappa=0.6078)real zerodiv ! Zero division handlingparameter (zerodiv=0.0000000001)real dpmin ! Pressure step for hydrostatic equationparameter (dpmin=10.)real rdg ! Ratio gas constant / Earth's gravityparameter (rdg=29.271)c Auxiliray variablesinteger i,j,k,lcharacter*80 varnameinteger isokinteger statinteger cdfid,ierr,cstidcharacter*80 cfnreal p1(1000),z1(1000),f1(1000),tv1(1000)real spline_f1(1000),spline_tv1(1000)integer n1real hhreal pmin,pmaxreal boundlat(100000),boundlon(1000000)integer nboundinteger il,ir,ju,jd,im,jmreal lat,lonreal distmin,distposcharacter*80 namereal pu,po,zu,zo,p,z,dp,p0,tvu,tvo,ffinteger lmin,nreal mean,nmeanreal psfcinteger count0,count1c Externalsreal sdis,kinkexternal sdis,kinkc -----------------------------------------------------------------c Read input fieldsc -----------------------------------------------------------------print*,'*********************************************************'print*,'* add2p *'print*,'*********************************************************'print*c Read in the parameter fileopen(10,file='fort.10')read(10,*) ml_fnread(10,*) zm_fnread(10,*) or_fnread(10,*) name,transxyif ( trim(name).ne.'TRANS_XY' ) stopread(10,*) name,psfcif ( trim(name).ne.'PS_CHANGE' ) stopclose(10)print*,trim(ml_fn)print*,trim(zm_fn)print*,trim(or_fn)print*c Get grid description for P file : model levelcall cdfopn(ml_fn,cdfid,ierr)if (ierr.ne.0) goto 998call getvars(cdfid,ml_nvars,ml_vnam,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 998isok=0varname='T'call 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)if (ierr.ne.0) goto 998call 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_dyif (ierr.ne.0) goto 998call gettimes(cdfid,ml_time,ml_ntimes,ierr)if (ierr.ne.0) goto 998call getstart(cstid,ml_idate,ierr)if (ierr.ne.0) goto 998call getpole(cstid,ml_pollon,ml_pollat,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 grid description for MOD filecall cdfopn(zm_fn,cdfid,ierr)if (ierr.ne.0) goto 997call getvars(cdfid,zm_nvars,zm_vnam,ierr)if (ierr.ne.0) goto 997call getcfn(cdfid,cfn,ierr)if (ierr.ne.0) goto 997call cdfopn(cfn,cstid,ierr)if (ierr.ne.0) goto 997isok=0varname='T'call check_varok(isok,varname,zm_vnam,zm_nvars)if (isok.ne.1) goto 997call getdef(cdfid,varname,zm_ndim,zm_mdv,zm_vardim,> zm_varmin,zm_varmax,zm_stag,ierr)if (ierr.ne.0) goto 997zm_nx =zm_vardim(1)zm_ny =zm_vardim(2)zm_nz =zm_vardim(3)zm_xmin=zm_varmin(1)zm_ymin=zm_varmin(2)call getlevs(cstid,zm_nz,zm_aklev,zm_bklev,zm_aklay,zm_bklay,ierr)if (ierr.ne.0) goto 997call getgrid(cstid,zm_dx,zm_dy,ierr)if (ierr.ne.0) goto 997zm_xmax=zm_xmin+real(zm_nx-1)*zm_dxzm_ymax=zm_ymin+real(zm_ny-1)*zm_dycall gettimes(cdfid,zm_time,zm_ntimes,ierr)if (ierr.ne.0) goto 997call getstart(cstid,zm_idate,ierr)if (ierr.ne.0) goto 997call getpole(cstid,zm_pollon,zm_pollat,ierr)if (ierr.ne.0) goto 997call clscdf(cstid,ierr)if (ierr.ne.0) goto 997call clscdf(cdfid,ierr)if (ierr.ne.0) goto 997c Get grid description for ORG filecall cdfopn(or_fn,cdfid,ierr)if (ierr.ne.0) goto 997call getvars(cdfid,or_nvars,or_vnam,ierr)if (ierr.ne.0) goto 997call getcfn(cdfid,cfn,ierr)if (ierr.ne.0) goto 997call cdfopn(cfn,cstid,ierr)if (ierr.ne.0) goto 997isok=0varname='P'call check_varok(isok,varname,or_vnam,or_nvars)if (isok.ne.1) goto 997call getdef(cdfid,varname,or_ndim,or_mdv,or_vardim,> or_varmin,or_varmax,or_stag,ierr)if (ierr.ne.0) goto 997or_nx =or_vardim(1)or_ny =or_vardim(2)or_nz =or_vardim(3)or_xmin=or_varmin(1)or_ymin=or_varmin(2)call getgrid(cstid,or_dx,or_dy,ierr)if (ierr.ne.0) goto 997or_xmax=or_xmin+real(or_nx-1)*or_dxor_ymax=or_ymin+real(or_ny-1)*or_dycall gettimes(cdfid,or_time,or_ntimes,ierr)if (ierr.ne.0) goto 997call getstart(cstid,or_idate,ierr)if (ierr.ne.0) goto 997call getpole(cstid,or_pollon,or_pollat,ierr)if (ierr.ne.0) goto 997call clscdf(cstid,ierr)if (ierr.ne.0) goto 997call clscdf(cdfid,ierr)if (ierr.ne.0) goto 997c Consistency check for the gridsif ( (abs(ml_xmin-zm_xmin).gt.eps).or.> (abs(ml_xmax-zm_xmax).gt.eps).or.> (abs(ml_ymin-zm_ymin).gt.eps).or.> (abs(ml_ymax-zm_ymax).gt.eps).or.> (abs(ml_dx -zm_dx ).gt.eps).or.> (abs(ml_dy -zm_dy ).gt.eps).or.> (abs(ml_time-zm_time).gt.eps).or.> (abs(ml_xmin-or_xmin).gt.eps).or.> (abs(ml_xmax-or_xmax).gt.eps).or.> (abs(ml_ymin-or_ymin).gt.eps).or.> (abs(ml_ymax-or_ymax).gt.eps).or.> (abs(ml_dx -or_dx ).gt.eps).or.> (abs(ml_dy -or_dy ).gt.eps) )>thenprint*,'P, GEO.MOD, GEO.ORG grids not consistent... Stop'print*,ml_xmin,zm_xmin,or_xminprint*,ml_ymin,zm_ymin,or_yminprint*,ml_dx, zm_dx ,or_dxprint*,ml_dy, zm_dy ,or_dyprint*,ml_time,zm_time,or_timestopendifc Allocate memory for input and output P fileallocate(ml_p3 (ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'error allocating ml_p3'allocate(ml_u3 (ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'error allocating ml_u3'allocate(ml_v3 (ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'error allocating ml_v3'allocate(ml_t3 (ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'error allocating ml_t3'allocate(ml_tv3 (ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'error allocating ml_tv3'allocate(ml_z3 (ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'error allocating ml_z3'allocate(ml_q3 (ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'error allocating ml_q3'allocate(ml_ps (ml_nx,ml_ny ),stat=stat)if (stat.ne.0) print*,'error allocating ml_ps'allocate(ml_oro (ml_nx,ml_ny ),stat=stat)if (stat.ne.0) print*,'error allocating ml_oro'allocate(ml_p0 (ml_nx,ml_ny,ml_nz),stat=stat)if (stat.ne.0) print*,'error allocating ml_p0'c Allocate memory for input GEO.MOD fileallocate(zm_p3(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating zm_p3'allocate(zm_u3(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating zm_u3'allocate(zm_v3(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating zm_v3'allocate(zm_t3(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating zm_t3'allocate(zm_z3(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating zm_z3'allocate(zm_rlat(zm_nx,zm_ny),stat=stat)if (stat.ne.0) print*,'error allocating zm_rlat'allocate(zm_rlon(zm_nx,zm_ny),stat=stat)if (stat.ne.0) print*,'error allocating zm_rlon'c Allocate memory for input GEO.ORG fileallocate(or_p3(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating zm_p3'allocate(or_t3(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating zm_t3'allocate(or_u3(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating zm_u3'allocate(or_v3(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating zm_v3'c Allocate memory for weighting function, flag and anomaliesallocate(weight(zm_nx,zm_ny),stat=stat)if (stat.ne.0) print*,'error allocating weight'allocate(dist (zm_nx,zm_ny),stat=stat)if (stat.ne.0) print*,'error allocating dist'allocate(flag_zm(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating flag'allocate(flag_ml(zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating flag'allocate(an_p3 (zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating an_p3'allocate(an_t3 (zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating an_t3'allocate(an_u3 (zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating an_u3'allocate(an_v3 (zm_nx,zm_ny,zm_nz),stat=stat)if (stat.ne.0) print*,'error allocating an_v3'c Read variables from P file : model levelscall cdfopn(ml_fn,cdfid,ierr)if (ierr.ne.0) goto 998varname='T'call getdat(cdfid,varname,ml_time,0,ml_t3,ierr)if (ierr.ne.0) goto 998print*,'R T ',trim(ml_fn)varname='U'call getdat(cdfid,varname,ml_time,0,ml_u3,ierr)if (ierr.ne.0) goto 998print*,'R U ',trim(ml_fn)varname='V'call getdat(cdfid,varname,ml_time,0,ml_v3,ierr)if (ierr.ne.0) goto 998print*,'R V ',trim(ml_fn)varname='Z'call getdat(cdfid,varname,ml_time,0,ml_z3,ierr)if (ierr.ne.0) goto 998print*,'R Z ',trim(ml_fn)varname='Q'call getdat(cdfid,varname,ml_time,0,ml_q3,ierr)if (ierr.ne.0) goto 998print*,'R Q ',trim(ml_fn)varname='PS'call getdat(cdfid,varname,ml_time,0,ml_ps,ierr)if (ierr.ne.0) goto 998print*,'R PS ',trim(ml_fn)varname='ORO'call getdat(cdfid,varname,ml_time,0,ml_oro,ierr)if (ierr.ne.0) goto 998print*,'R ORO ',trim(ml_fn)call clscdf(cdfid,ierr)if (ierr.ne.0) goto 998c Read variables from GEO.MODcall cdfopn(zm_fn,cdfid,ierr)if (ierr.ne.0) goto 997varname='T'call getdat(cdfid,varname,zm_time,0,zm_t3,ierr)if (ierr.ne.0) goto 997print*,'R T ',trim(zm_fn)varname='U'call getdat(cdfid,varname,zm_time,0,zm_u3,ierr)if (ierr.ne.0) goto 997print*,'R U ',trim(zm_fn)varname='V'call getdat(cdfid,varname,zm_time,0,zm_v3,ierr)if (ierr.ne.0) goto 997print*,'R V ',trim(zm_fn)varname='P'call getdat(cdfid,varname,zm_time,0,zm_p3,ierr)if (ierr.ne.0) goto 997print*,'R P ',trim(zm_fn)varname='RLAT'call getdat(cdfid,varname,zm_time,0,zm_rlat,ierr)if (ierr.ne.0) goto 997print*,'R RLAT ',trim(zm_fn)varname='RLON'call getdat(cdfid,varname,zm_time,0,zm_rlon,ierr)if (ierr.ne.0) goto 997print*,'R RLON ',trim(zm_fn)call clscdf(cdfid,ierr)if (ierr.ne.0) goto 997c Read variables from GEO.ORGcall cdfopn(or_fn,cdfid,ierr)if (ierr.ne.0) goto 998varname='P'call getdat(cdfid,varname,or_time,0,or_p3,ierr)if (ierr.ne.0) goto 998print*,'R P ',trim(or_fn)varname='U'call getdat(cdfid,varname,or_time,0,or_u3,ierr)if (ierr.ne.0) goto 998print*,'R U ',trim(or_fn)varname='V'call getdat(cdfid,varname,or_time,0,or_v3,ierr)if (ierr.ne.0) goto 998print*,'R V ',trim(or_fn)varname='T'call getdat(cdfid,varname,or_time,0,or_t3,ierr)if (ierr.ne.0) goto 998print*,'R T ',trim(or_fn)call clscdf(cdfid,ierr)if (ierr.ne.0) goto 998c Initialize the height levels of the Z filedo i=1,zm_nxdo j=1,zm_nydo k=1,zm_nzzm_z3(i,j,k)=zm_aklay(k)enddoenddoenddoc Calculate 3d pressure field on model levelsprint*,'C P (ORIGINAL)'do k=1,ml_nzdo i=1,ml_nxdo j=1,ml_nyif (abs(ml_stag(3)+0.5).lt.eps) thenml_p0(i,j,k)=ml_aklay(k)+ml_bklay(k)*ml_ps(i,j)elseml_p0(i,j,k)=ml_aklev(k)+ml_bklev(k)*ml_ps(i,j)endifenddoenddoenddoc Calculate 3d anomalies due to inversionprint*,'C DP (MODIFIED-ORIGINAL)'print*,'C DU (MODIFIED-ORIGINAL)'print*,'C DV (MODIFIED-ORIGINAL)'print*,'C DT (MODIFIED-ORIGINAL)'do k=1,zm_nzdo i=1,zm_nxdo j=1,zm_nyc Pif ( ( abs(zm_p3(i,j,k)-zm_mdv).gt.eps).and.> ( abs(or_p3(i,j,k)-or_mdv).gt.eps) )> thenan_p3(i,j,k) = zm_p3(i,j,k) - or_p3(i,j,k)elseif ( poisson.eq.1 ) thenan_p3(i,j,k) = zm_mdvelsean_p3(i,j,k) = 0.endifc Tif ( ( abs(zm_t3(i,j,k)-zm_mdv).gt.eps).and.> ( abs(or_t3(i,j,k)-or_mdv).gt.eps) )> thenan_t3(i,j,k) = zm_t3(i,j,k) - or_t3(i,j,k)elseif ( poisson.eq.1 ) thenan_t3(i,j,k) = zm_mdvelsean_t3(i,j,k) = 0.endifc Uif ( ( abs(zm_u3(i,j,k)-zm_mdv).gt.eps).and.> ( abs(or_u3(i,j,k)-or_mdv).gt.eps) )> thenan_u3(i,j,k) = zm_u3(i,j,k) - or_u3(i,j,k)elseif ( poisson.eq.1 ) thenan_u3(i,j,k) = zm_mdvelsean_u3(i,j,k) = 0.endifc Vif ( ( abs(zm_v3(i,j,k)-zm_mdv).gt.eps).and.> ( abs(or_v3(i,j,k)-or_mdv).gt.eps) )> thenan_v3(i,j,k) = zm_v3(i,j,k) - or_v3(i,j,k)elseif ( poisson.eq.1 ) thenan_v3(i,j,k) = zm_mdvelsean_v3(i,j,k) = 0.endifenddoenddoenddoc ----------------------------------------------------------------c Get the weight function for the inset (from 1 inside to 0 outside)c ----------------------------------------------------------------print*,'C BOUNDARY FILTER'c Init the weight function (1 inside, 0 outside)do i=1,ml_nxdo j=1,ml_nyif ( (zm_rlat(i,j).lt. -90.).or.> (zm_rlat(i,j).gt. 90.).or.> (zm_rlon(i,j).lt.-180.).or.> (zm_rlon(i,j).gt. 180.) ) thenweight(i,j)=0.elseweight(i,j)=1.endifenddoenddoc Get a list of all boundary pointsnbound=0do i=1,ml_nxdo j=1,ml_nyc Get neighbouring pointsir=i+1if (ir.gt.ml_nx) ir=ml_nxil=i-1if (il.lt. 1) il=1ju=j+1if (ju.gt.ml_ny) ju=ml_nyjd=j-1if (jd.lt. 1) jd=1c A boundary point has a 0/1 switchif (abs(weight(i,j)-0.).lt.eps) thenif ( (abs(weight(ir, j)-1.).lt.eps).or.> (abs(weight(il, j)-1.).lt.eps).or.> (abs(weight(i ,ju)-1.).lt.eps).or.> (abs(weight(i ,jd)-1.).lt.eps).or.> (abs(weight(ir,ju)-1.).lt.eps).or.> (abs(weight(ir,jd)-1.).lt.eps).or.> (abs(weight(il,ju)-1.).lt.eps).or.> (abs(weight(il,jd)-1.).lt.eps).or.> (abs(weight(ir,ju)-1.).lt.eps).or.> (abs(weight(il,ju)-1.).lt.eps).or.> (abs(weight(ir,jd)-1.).lt.eps).or.> (abs(weight(il,jd)-1.).lt.eps) ) thennbound=nbound+1boundlon(nbound)=ml_xmin+real(i-1)*ml_dxboundlat(nbound)=ml_ymin+real(j-1)*ml_dyendifendifenddoenddoc Get the distance from the subdomaindo i=1,ml_nxdo j=1,ml_nylon=ml_xmin+real(i-1)*ml_dxlat=ml_ymin+real(j-1)*ml_dydistmin=sdis(lon,lat,boundlon(1),boundlat(1))do k=2,nbounddistpos=sdis(lon,lat,boundlon(k),boundlat(k))if (distpos.lt.distmin) distmin=distposenddoif ( abs(weight(i,j)-1.).lt.eps) thendist(i,j)=distminelsedist(i,j)=-distminendifenddoenddoc Set the new weightsdo i=1,ml_nxdo j=1,ml_nyif (weight(i,j).gt.0.) thenweight(i,j)=kink(dist(i,j),transxy)endifenddoenddoc ----------------------------------------------------------------c Remove MDV regions in input fieldc ----------------------------------------------------------------if ( poisson.ne.1 ) goto 120c Define region for mdv fillingdo i=1,zm_nxdo j=1,zm_nydo k=1,zm_nzc Get neighbour of grid pointil = i-1if (il.lt.1) il=1ir = i+1if ( ir.gt.zm_nx ) ir=zm_nxjd = j-1if (jd.lt.1) jd=1ju = j+1if ( ju.gt.zm_ny ) ju=zm_nyc Set flag 2 for boundary and exterior pointsif ( (abs(zm_rlat(il, j)-zm_mdv).lt.eps).or.> (abs(zm_rlat(ir, j)-zm_mdv).lt.eps).or.> (abs(zm_rlat(i , j)-zm_mdv).lt.eps).or.> (abs(zm_rlat(il,ju)-zm_mdv).lt.eps).or.> (abs(zm_rlat(ir,ju)-zm_mdv).lt.eps).or.> (abs(zm_rlat(i ,ju)-zm_mdv).lt.eps).or.> (abs(zm_rlat(il,jd)-zm_mdv).lt.eps).or.> (abs(zm_rlat(ir,jd)-zm_mdv).lt.eps).or.> (abs(zm_rlat(i ,jd)-zm_mdv).lt.eps) )> thenflag_zm(i,j,k) = 2an_p3(i,j,k) = 0.an_u3(i,j,k) = 0.an_v3(i,j,k) = 0.an_t3(i,j,k) = 0.c Set flag 1 for interior MDV pointselseif ( abs(an_p3(i,j,k)-zm_mdv).le.eps ) thenflag_zm(i,j,k) = 1c Set flag 0 for interior valid pointselseflag_zm(i,j,k) = 0endifenddoenddoenddoc Apply mdv fillingprint*,'C DP (POISSON FILLING)'call mdvfill(an_p3,an_p3,flag_zm,zm_nx,zm_ny,zm_nz,100)print*,'C DT (POISSON FILLING)'call mdvfill(an_t3,an_t3,flag_zm,zm_nx,zm_ny,zm_nz,100)print*,'C DU (POISSON FILLING)'call mdvfill(an_u3,an_u3,flag_zm,zm_nx,zm_ny,zm_nz,100)print*,'C DV (POISSON FILLING)'call mdvfill(an_v3,an_v3,flag_zm,zm_nx,zm_ny,zm_nz,100)c Special treatment: if the number of missing values surpasses 50%c on a level, then the anomaly is imported from the level abovedo k=zm_nz-1,1,-1count1 = 0count0 = 0do i=1,zm_nxdo j= 1,zm_nyif ( flag_zm(i,j,k).eq.1 ) count1 = count1 + 1if ( flag_zm(i,j,k).eq.0 ) count0 = count0 + 1enddoenddoif ( count1.gt.count0 ) thenprint*,'C P (IMPORTING FROM LEVEL ABOVE)',kdo i=1,zm_nxdo j= 1,zm_nyan_p3(i,j,k) = an_p3(i,j,k+1)flag_zm(i,j,k) = flag_zm(i,j,k+1)enddoenddoprint*,'C U (IMPORTING FROM LEVEL ABOVE)',kdo i=1,zm_nxdo j= 1,zm_nyan_u3(i,j,k) = an_u3(i,j,k+1)flag_zm(i,j,k) = flag_zm(i,j,k+1)enddoenddoprint*,'C V (IMPORTING FROM LEVEL ABOVE)',kdo i=1,zm_nxdo j= 1,zm_nyan_v3(i,j,k) = an_v3(i,j,k+1)flag_zm(i,j,k) = flag_zm(i,j,k+1)enddoenddoprint*,'C T (IMPORTING FROM LEVEL ABOVE)',kdo i=1,zm_nxdo j= 1,zm_nyan_t3(i,j,k) = an_t3(i,j,k+1)flag_zm(i,j,k) = flag_zm(i,j,k+1)enddoenddoendifenddoc Write new fields for testsif ( test.eq.1 ) thencall cdfwopn(zm_fn,cdfid,ierr)if (ierr.ne.0) goto 994isok=0varname='P_ANO'call check_varok(isok,varname,zm_vnam,zm_nvars)if (isok.eq.0) thencall putdef(cdfid,varname,zm_ndim,zm_mdv,zm_vardim,> zm_varmin,zm_varmax,zm_stag,ierr)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,zm_time,0,an_p3,ierr)if (ierr.ne.0) goto 994print*,'W P_ANO ',trim(zm_fn)isok=0varname='T_ANO'call check_varok(isok,varname,zm_vnam,zm_nvars)if (isok.eq.0) thencall putdef(cdfid,varname,zm_ndim,zm_mdv,zm_vardim,> zm_varmin,zm_varmax,zm_stag,ierr)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,zm_time,0,an_t3,ierr)if (ierr.ne.0) goto 994print*,'W T_ANO ',trim(zm_fn)isok=0varname='U_ANO'call check_varok(isok,varname,zm_vnam,zm_nvars)if (isok.eq.0) thencall putdef(cdfid,varname,zm_ndim,zm_mdv,zm_vardim,> zm_varmin,zm_varmax,zm_stag,ierr)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,zm_time,0,an_u3,ierr)if (ierr.ne.0) goto 994print*,'W U_ANO ',trim(zm_fn)isok=0varname='V_ANO'call check_varok(isok,varname,zm_vnam,zm_nvars)if (isok.eq.0) thencall putdef(cdfid,varname,zm_ndim,zm_mdv,zm_vardim,> zm_varmin,zm_varmax,zm_stag,ierr)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,zm_time,0,an_v3,ierr)if (ierr.ne.0) goto 994print*,'W V_ANO ',trim(zm_fn)call clscdf(cdfid,ierr)if (ierr.ne.0) goto 994endifc Exit point for SOR solver120 continuec ----------------------------------------------------------------c Change surface pressure and get 3d presure fieldc ----------------------------------------------------------------print*,'C PS'c Change surface pressure: based on PV inversion on GEOdo i=1,ml_nxdo j=1,ml_nyc Make vertical profile of pressure availablen1=0do k=1,zm_nzn1=n1+1p1(n1)=an_p3(i,j,k)z1(n1)=zm_z3(i,j,k)enddoif ( n1.ne.0 ) thenc Keep the original surface pressure (psfc=0)if ( abs(psfc).lt.eps ) thenml_ps(i,j) = ml_ps(i,j)c Take the full change of surface pressure (psfc=1);c Interpolation/extrapolation with a natural cubic splineelseif ( abs(psfc-1.).lt.eps ) thencall spline (z1,p1,n1,1.e30,1.e30,spline_f1)call splint (z1,p1,spline_f1,n1,ml_oro(i,j),hh)ml_ps(i,j)=ml_ps(i,j) + hh*weight(i,j)c Only take a fractional change of surface pressurec Interpolation/extrapolation with a natural cubic splineelsecall spline (z1,p1,n1,1.e30,1.e30,spline_f1)call splint (z1,p1,spline_f1,n1,ml_oro(i,j),hh)ml_ps(i,j)=ml_ps(i,j) + hh*psfc*weight(i,j)endifendifenddoenddoc Calculate 3d pressure field on model levelsprint*,'C P'do k=1,ml_nzdo i=1,ml_nxdo j=1,ml_nyif (abs(ml_stag(3)+0.5).lt.eps) thenml_p3(i,j,k)=ml_aklay(k)+ml_bklay(k)*ml_ps(i,j)elseml_p3(i,j,k)=ml_aklev(k)+ml_bklev(k)*ml_ps(i,j)endifenddoenddoenddoc ----------------------------------------------------------------c Get T,U,V at the new pressure levels, based on the original P filec ----------------------------------------------------------------c Interpolate T from original P file to new pressure levelsprint*,'C T (ORIGINAL)'do i=1,ml_nxdo j=1,ml_nyn1=0do k=ml_nz,1,-1n1=n1+1f1(n1)=ml_t3(i,j,k)p1(n1)=ml_p0(i,j,k)enddocall spline (p1,f1,n1,1.e30,1.e30,spline_f1)do k=1,ml_nzcall splint (p1,f1,spline_f1,n1,ml_p3(i,j,k),hh)ml_t3(i,j,k)=hhenddoenddoenddoc Interpolate U from original P file to new pressure levelsprint*,'C U (ORIGINAL)'do i=1,ml_nxdo j=1,ml_nyn1=0do k=ml_nz,1,-1n1=n1+1f1(n1)=ml_u3(i,j,k)p1(n1)=ml_p0(i,j,k)enddocall spline (p1,f1,n1,1.e30,1.e30,spline_f1)do k=1,ml_nzcall splint (p1,f1,spline_f1,n1,ml_p3(i,j,k),hh)ml_u3(i,j,k)=hhenddoenddoenddoc Interpolate V from original P file to new pressure levelsprint*,'C V (ORIGINAL)'do i=1,ml_nxdo j=1,ml_nyn1=0do k=ml_nz,1,-1n1=n1+1f1(n1)=ml_v3(i,j,k)p1(n1)=ml_p0(i,j,k)enddocall spline (p1,f1,n1,1.e30,1.e30,spline_f1)do k=1,ml_nzcall splint (p1,f1,spline_f1,n1,ml_p3(i,j,k),hh)ml_v3(i,j,k)=hhenddoenddoenddoc ----------------------------------------------------------------c Add T,U,V anomalies at the new pressure levelsc ----------------------------------------------------------------c Change temperature fieldprint*,'C T (ANOMALY)'do i=1,ml_nxdo j=1,ml_nyc Make vertical profile of temperature availablen1=0pmax=-100.pmin=2000.do k=zm_nz,1,-1if ((abs(an_t3(i,j,k)-zm_mdv).gt.eps).and.> (zm_z3(i,j,k).gt.ml_oro(i,j)).and.> (abs(zm_p3(i,j,k)-zm_mdv).gt.eps)) thenn1=n1+1f1(n1)=an_t3(i,j,k)p1(n1)=zm_p3(i,j,k)if (p1(n1).lt.pmin) pmin=p1(n1)if (p1(n1).gt.pmax) pmax=p1(n1)endifenddopmin=pmin-dpextra*pminpmax=pmax+dpextra+pmaxc Cubic spline interpolationif (n1.gt.0) thencall spline (p1,f1,n1,1.e30,1.e30,spline_f1)do k=1,ml_nzif ( (ml_p3(i,j,k).gt.pmin).and.> (ml_p3(i,j,k).lt.pmax) ) thencall splint (p1,f1,spline_f1,n1,ml_p3(i,j,k),hh)ml_t3(i,j,k)=ml_t3(i,j,k) + hh*weight(i,j)endifenddoendifenddoenddoc Change zonal velocity fieldprint*,'C U'do i=1,ml_nxdo j=1,ml_nyc Make vertical profile of zonal velocity availablen1=0pmax=-100.pmin=2000.do k=zm_nz,1,-1if ((abs(an_u3(i,j,k)-zm_mdv).gt.eps).and.> (zm_z3(i,j,k).gt.ml_oro(i,j)).and.> (abs(zm_p3(i,j,k)-zm_mdv).gt.eps)) thenn1=n1+1f1(n1)=an_u3(i,j,k)p1(n1)=zm_p3(i,j,k)if (p1(n1).lt.pmin) pmin=p1(n1)if (p1(n1).gt.pmax) pmax=p1(n1)endifenddopmin=pmin-dpextra*pminpmax=pmax+dpextra*pmaxc Cubic spline interpolationif (n1.gt.0) thencall spline (p1,f1,n1,1.e30,1.e30,spline_f1)do k=1,ml_nzif ( (ml_p3(i,j,k).gt.pmin).and.> (ml_p3(i,j,k).lt.pmax) ) thencall splint (p1,f1,spline_f1,n1,ml_p3(i,j,k),hh)ml_u3(i,j,k)=ml_u3(i,j,k) + hh*weight(i,j)endifenddoendifenddoenddoc Change meridional velocity fieldprint*,'C V'do i=1,ml_nxdo j=1,ml_nyc Make vertical profile of zonal velocity availablen1=0pmax=-100.pmin=2000.do k=zm_nz,1,-1if ((abs(an_v3(i,j,k)-zm_mdv).gt.eps).and.> (zm_z3(i,j,k).gt.ml_oro(i,j)).and.> (abs(zm_p3(i,j,k)-zm_mdv).gt.eps)) thenn1=n1+1f1(n1)=an_v3(i,j,k)p1(n1)=zm_p3(i,j,k)if (p1(n1).lt.pmin) pmin=p1(n1)if (p1(n1).gt.pmax) pmax=p1(n1)endifenddopmin=pmin-dpextra*pminpmax=pmax+dpextra*pmaxc Cubic spline interpolationif (n1.gt.0) thencall spline (p1,f1,n1,1.e30,1.e30,spline_f1)do k=1,ml_nzif ( (ml_p3(i,j,k).gt.pmin).and.> (ml_p3(i,j,k).lt.pmax) ) thencall splint (p1,f1,spline_f1,n1,ml_p3(i,j,k),hh)ml_v3(i,j,k)=ml_v3(i,j,k) + hh*weight(i,j)endifenddoendifenddoenddoc ---------------------------------------------------------------------c Change geopotential heightc ---------------------------------------------------------------------c Interpolate Z from original P file to new pressure levelsprint*,'C Z (ORIGINAL)'do i=1,ml_nxdo j=1,ml_nyn1=0do k=ml_nz,1,-1n1=n1+1f1(n1)=ml_z3(i,j,k)p1(n1)=ml_p0(i,j,k)enddocall spline (p1,f1,n1,1.e30,1.e30,spline_f1)do k=1,ml_nzcall splint (p1,f1,spline_f1,n1,ml_p3(i,j,k),hh)ml_z3(i,j,k)=hhenddoenddoenddoc 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 Add geopotential height anomaly: first, the pressure anomaly isc interpolated to the new position, then it is transformed intoc a correction of geopotential height with the hydrostatic equationprint*,'C DZ (MODIFIED -ORIGINAL)'do i=1,ml_nxdo j=1,ml_nyc Make vertical profile of pressure availablen1=0pmax=-100.pmin=2000.do k=zm_nz,1,-1if ((abs(an_p3(i,j,k)-zm_mdv).gt.eps).and.> (zm_z3(i,j,k).gt.ml_oro(i,j)).and.> (abs(zm_p3(i,j,k)-zm_mdv).gt.eps)) thenn1=n1+1f1(n1)=an_p3(i,j,k)p1(n1)=zm_p3(i,j,k)if (p1(n1).lt.pmin) pmin=p1(n1)if (p1(n1).gt.pmax) pmax=p1(n1)endifenddopmin=pmin-dpextra*pminpmax=pmax+dpextra*pmaxc Cubic spline interpolation and conversion dp -> dzif (n1.gt.0) thencall spline (p1,f1,n1,1.e30,1.e30,spline_f1)do k=1,ml_nzif ( (ml_p3(i,j,k).gt.pmin).and.> (ml_p3(i,j,k).lt.pmax) ) thencall splint (p1,f1,spline_f1,n1,ml_p3(i,j,k),hh)hh = -rdg * ml_tv3(i,j,k) * hh/ml_p3(i,j,k)ml_z3(i,j,k)=ml_z3(i,j,k) + hh*weight(i,j)endifenddoendifenddoenddoc ----------------------------------------------------------------c Remove unrealistic values from final fieldsc ----------------------------------------------------------------if ( poisson.ne.1 ) goto 120c Define region for mdv fillingcount1 = 0do i=1,ml_nxdo j=1,ml_nydo k=1,ml_nzc Get neighbour of grid pointil = i-1if (il.lt.1) il=1ir = i+1if ( ir.gt.ml_nx ) ir=ml_nxjd = j-1if (jd.lt.1) jd=1ju = j+1if ( ju.gt.ml_ny ) ju=ml_nyc Set flag 2 for boundary and exterior pointsif ( (abs(zm_rlat(il, j)-zm_mdv).lt.eps).or.> (abs(zm_rlat(ir, j)-zm_mdv).lt.eps).or.> (abs(zm_rlat(i , j)-zm_mdv).lt.eps).or.> (abs(zm_rlat(il,ju)-zm_mdv).lt.eps).or.> (abs(zm_rlat(ir,ju)-zm_mdv).lt.eps).or.> (abs(zm_rlat(i ,ju)-zm_mdv).lt.eps).or.> (abs(zm_rlat(il,jd)-zm_mdv).lt.eps).or.> (abs(zm_rlat(ir,jd)-zm_mdv).lt.eps).or.> (abs(zm_rlat(i ,jd)-zm_mdv).lt.eps) )> thenflag_ml(i,j,k) = 2c Set flag 1 for interior unphysical pointselseif ( ( abs(ml_t3(i,j,k)).gt.500. ).or.> ( abs(ml_u3(i,j,k)).gt.500. ).or.> ( abs(ml_v3(i,j,k)).gt.500. ) )> thenflag_ml(i,j,k) = 1count1 = count1 + 1c Set flag 0 for interior valid pointselseflag_ml(i,j,k) = 0endifenddoenddoenddoprint*,'C MASK UNREALISTIC VALUES FOR T,U,V',count1c Apply mdv fillingprint*,'C T (POISSON FILLING)'call mdvfill(ml_t3,ml_t3,flag_ml,ml_nx,ml_ny,ml_nz,10)print*,'C U (POISSON FILLING)'call mdvfill(ml_u3,ml_u3,flag_ml,ml_nx,ml_ny,ml_nz,10)print*,'C V (POISSON FILLING)'call mdvfill(ml_v3,ml_v3,flag_ml,ml_nx,ml_ny,ml_nz,10)c ----------------------------------------------------------------c Write modified fields to P filec ----------------------------------------------------------------c Open output filecall cdfwopn(ml_fn,cdfid,ierr)if (ierr.ne.0) goto 994c Write surface pressureisok=0varname='PS'call check_varok(isok,varname,ml_vnam,ml_nvars)if (isok.eq.0) thenml_vardim(3)=3call putdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,> ml_varmin,ml_varmax,ml_stag,ierr)if (ierr.ne.0) goto 994ml_vardim(3)=4endifcall putdat(cdfid,varname,ml_time,0,ml_ps,ierr)if (ierr.ne.0) goto 994print*,'W PS ',trim(ml_fn)c Write temperatureisok=0varname='T'call check_varok(isok,varname,ml_vnam,ml_nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,> ml_varmin,ml_varmax,ml_stag,ierr)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,ml_time,0,ml_t3,ierr)if (ierr.ne.0) goto 994print*,'W T ',trim(ml_fn)c Write zonal windisok=0varname='U'call check_varok(isok,varname,ml_vnam,ml_nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,> ml_varmin,ml_varmax,ml_stag,ierr)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,ml_time,0,ml_u3,ierr)if (ierr.ne.0) goto 994print*,'W U ',trim(ml_fn)c Write meridional windisok=0varname='V'call check_varok(isok,varname,ml_vnam,ml_nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,> ml_varmin,ml_varmax,ml_stag,ierr)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,ml_time,0,ml_v3,ierr)if (ierr.ne.0) goto 994print*,'W V ',trim(ml_fn)c Write geopotential heightisok=0varname='Z'call check_varok(isok,varname,ml_vnam,ml_nvars)if (isok.eq.0) thencall putdef(cdfid,varname,ml_ndim,ml_mdv,ml_vardim,> ml_varmin,ml_varmax,ml_stag,ierr)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,ml_time,0,ml_z3,ierr)if (ierr.ne.0) goto 994print*,'W Z ',trim(ml_fn)c Filter matrix (only in test mode)if (test.eq.1) thenisok=0varname='DIST'call 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)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,ml_time,1,dist,ierr)if (ierr.ne.0) goto 994print*,'W DIST ',trim(ml_fn)isok=0varname='WEIGHT'call 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)if (ierr.ne.0) goto 994endifcall putdat(cdfid,varname,ml_time,1,weight,ierr)if (ierr.ne.0) goto 994print*,'W WEIGHT ',trim(ml_fn)endifc Close output filecall clscdf(cdfid,ierr)if (ierr.ne.0) goto 994c ----------------------------------------------------------------c Exception handlingc ----------------------------------------------------------------stop998 print*,'Problem with input netcdf file ',trim(ml_fn)stop997 print*,'Problem with input netcdf file ',trim(zm_fn)stop994 print*,'Problem with output netcdf file ',trim(ml_fn)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 Natural cubic spline /from Numerical Recipes)c -------------------------------------------------------------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 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 Rene's KINK function (for smoothing at bounadries)C -----------------------------------------------------------------real function kink (x,a)implicit nonec declaration of parametersreal x,ac parametersreal piparameter (pi=3.1415926535)if (x.lt.0.) thenkink=0.elseif (x.gt.a) thenkink=1.elsekink=(1.+cos(pi*(x-a)/a))/2.endifreturnendC -----------------------------------------------------------------c Rene's KINK function (for smoothing at bounadries)C -----------------------------------------------------------------subroutine mdvfill (out,inp,flag,nx,ny,nz,maxiter)implicit nonec Declaration of subroutine parametersinteger nx,ny,nzreal inp (nx,ny,nz)real out (nx,ny,nz)integer flag(nx,ny,nz)integer maxiterc Parametersreal omega ! Omega fopr SORparameter (omega=1.5)c Auxiliary variablesinteger i,j,kinteger iterreal tmp0(nx,ny,nz)real tmp1(nx,ny,nz)integer il,ir,ju,jdinteger countreal mean(nz)c Calculate mean of variable for all levelsdo k=1,nzmean(k) = 0.count = 0do i=1,nxdo j=1,nyif ( flag(i,j,k).eq.0 ) thencount = count + 1mean(k) = mean(k) + inp(i,j,k)endifenddoenddoif ( count.ne.0 ) thenmean(k) = mean(k)/real(count)elsemean(k) = 0.endifenddoc Create first guessdo k=1,nzdo i=1,nxdo j=1,nyif ( flag(i,j,k).eq.0 ) thentmp0(i,j,k) = inp(i,j,k)elsetmp0(i,j,k) = mean(k)endifenddoenddoenddoc SOR iterationsiter = 0122 continuec Loop over all pointsdo k=1,nzdo i=1,nxdo j=1,nyc Apply the updating only for specified pointsif ( flag(i,j,k).ne.1 ) goto 121c Get neighbouring points - no handling of periodic domains!il = i-1if (il.lt.1) il=1ir = i+1if ( ir.gt.nx ) ir=nxjd = j-1if (jd.lt.1) jd=1ju = j+1if ( ju.gt.ny ) ju=nyc Update fieldtmp1(i,j,k) = 0.25 * ( tmp0(il,j,k) + tmp0(ir,j,k) +> tmp0(i,ju,k) + tmp0(i,jd,k) )tmp0(i,j,k) = omega * tmp1(i,j,k) +> (1. - omega) * tmp1(i,j,k)c Exit point for loop121 continueenddoenddoenddoc Decide whether further iterations are needediter = iter + 1if ( iter.lt.maxiter) goto 122c Save outputdo i=1,nxdo j=1,nydo k=1,nzif ( flag(i,j,k).eq.1 ) thenout(i,j,k) = tmp0(i,j,k)endifenddoenddoenddoendc