SUBROUTINE FBARN(XLATN,NR,NC,XGA,XGD,XGE,XDA, * XROW,XCOL,NSTA,XINC,IFREQ,IGUESS) C $ SUBROUTINE FBARN(XLATN,NR,NC,XGA,XGD,XGE,XDA, C $ *XROW,XCOL,NSTA,XINC,IFREQ,IGUESS) (WLH) C $ FAST VERSION OF BARNES INTERPOLATION OF RANDOMLY LOCATED OBSERVATIONS C $ INTO UNIFORM LATITUDE-LONGITUDE GRID FOR ONE SET OF OBSERVATIONS. C $ INPUT: C $ XLATN = (R) NORTH LATITUDE OF GRID TOP IN DEGREES C $ NR = (I) # ROWS IN GRID C $ NC = (I) # COLUMNS IN GRID C $ XDA =(R) ARRAY XDA(NSTA) CONTAINING OBSERVATIONS C $ XROW = (R) ARRAY XROW(NSTA) CONTAINING ROW LOCATIONS OF OBSERVATIONS C $ XCOL = (R) ARRAY XCOL(NSTA) CONTAINING COLUMN LOCATIONS OF OBSERVATIONS C $ XROW & XCOL ARE MEASURED AS GRID ROW,COL . THUS AN OBSERVATION C $ AT THE UPPER LEFT GRID POINT WOULD HAVE XROW & XCOL BOTH = 1.0 C $ ****** WARNING ****** THE VALUES IN XDA, XROW & XCOL C $ ARE CHANGED BY THIS ROUTINE C $ NSTA = (I) # OF OBSERVATIONS ( STATIONS ) C $ XINC = (R) LATITUDE BETWEEN ROWS, IN DEGREES C $ IFREQ = (I) LOWPASS FILTER BANDWIDTH PARAMETER, INVERSELY C $ PROPORTIONAL TO SPATIAL FREQUENCY. GOOD VALUES FOR IFREQ DEPEND C $ ON STATION DENSITY PER GRID SQUARE. TOO LOW A VALUE MAY CAUSE A C $ FLOATING POINT ABORT. VALUES FROM 30 TO 60 ARE COMMON ON MCIDAS C $ IGUESS = (I) NON-ZERO IF GUESS GRID INPUT THROUGH XGA C $ OUTPUT: C $ XGA = (R) ARRAY XGA(NR, NC), INTERPOLATED FROM XDA C $ WORK: C $ XGD = (R) ARRAY XGD(NR,NC) FOR WEIGHT SUM DENOMINATOR FOR 1ST PASS C $ XGE = (R) ARRAY XGE(NR,NC) FOR WEIGHT SUM DENOMINATOR FOR 2ND PASS C $$ FBARN = OBSERVATION, GRID, COMPUTATION C C ALGORITHM AND SUBROUTINE BY BILL HIBBARD, SEPT 1979. C THE COMPUTING TIME OF THIS ALGORITHM IS PROPORTIONAL TO C NR*NC+NSTA*LOG(NSTA), COMPARED TO NR*NC*NSTA FOR INTPO. C THE PARAMETERS ARE IDENTICAL TO THE PARAMETERS FOR THE INTPO ROUTINE C IN THE MCIDAS SVCLIB LIBRARY, EXCEPT FOR THE ADDITION OF THE WORK C ARRAYS XGD & XGE AND THE INPUT VARIABLE IGUESS. IN PARTICULAR, IF C IFREQ IS THE SAME IN THIS ROUTINE AND IN INTPO, THEN THEY SHOULD GIVE C THE SAME INTERPOLATIONS, UP TO THE APPROXIMATION. C C-----*** WARNING *** ***(WARNING!)************ C THE VALUES IN XDA, XROW & XCOL ARE CHANGED BY THIS ROUTINE C PARAMETER (MXROW=120,MXCOL=120) REAL*8 DEG2RAD, PI DIMENSION XGA(*),XGD(*),XGE(*) DIMENSION XDA(*) DIMENSION XROW(*),XCOL(*) COMMON/CONS/NRP C THE DIMENSION OF IST MUST BE AT LEAST NR+2 DIMENSION IST(MXROW+2) DIMENSION EXT(102) C THE DIMENSION OF DBA, DGA, DBD, DBE, DGD, AND C DGE MUST ALL BE AT LEAST NC DIMENSION DBA(MXCOL),DGA(MXCOL) DIMENSION DBD(MXCOL),DBE(MXCOL),DGD(MXCOL),DGE(MXCOL) C THESE CONSTANTS DEFINE AN APPROXIMATION TO EXP(-X**2) DATA CLAMB/1.12045/,BETA/2.34/,GAMA/2.7495/ C THIS CONSTANT DEFINES THE CHANGE IN BANDWIDTH FROM THE FIRST TO SECOND C PASS DATA SECND/1.825741858/ PI = 4.D0*ATAN(1.D0) DEG2RAD = PI/180.D0 C THIS CONSTANT DEFINES THE INTEGER SCALING NRP=NR+1 IF(NR .GT. MXROW .OR. NR .LT. 1) GO TO 999 IF(NC .GT. MXCOL .OR. NC .LT. 1) GO TO 999 IF(NSTA .LT. 2) GO TO 999 C C C TWO DIMENSIONAL HEAP SORT OF STATIONS. GROUPS BETWEEN HORIZONTAL C GRID LINES ARE SORTED BY LONGITUDE. THE GROUPS ARE ORDERED BY C LATITUDE NSTAH=NSTA/2 DO 1 NN=1,NSTAH CALL HEAPFY(XDA,XROW,XCOL,NSTAH+1-NN,NSTA) 1 CONTINUE DO 2 NN=2,NSTA CALL INTER(XDA,XROW,XCOL,1,NSTA+2-NN) CALL HEAPFY(XDA,XROW,XCOL,1,NSTA+1-NN) 2 CONTINUE C GENERATE POINTERS TO STARTS OF GROUPS OF STATIONS BETWEEN HORIZONTAL C GRID LINES NSTAP=NSTA+1 NRPP=NR+2 DO 3 I=1,NRPP 3 IST(I)=NSTAP DO 4 N=1,NSTA K=XROW(N)+1. IF(K .LT. 1) K=1 IF(K .GT. NRP) K=NRP IF(IST(K) .GT. N) IST(K)=N 4 CONTINUE MAX=NSTAP DO 5 II=1,NRP I=NRP+1-II IF(IST(I) .LE. MAX) GO TO 5 IST(I)=MAX 5 MAX=IST(I) C CALCULATE EXPONENTS FROM LOW PASS BANDWIDTH PARAMETER IFREQ FREQ=IFREQ FF=SQRT(10.0/FREQ) FFA=FF*SECND SECI=1.0/SECND BG=BETA/GAMA BC=FF*BETA GC=FF*GAMA BCA=FFA*BETA GCA=FFA*GAMA BCF=SECI*BG GCF=SECI BCAF=BG GCAF=1.0 C FILL LOOKUP TABLE FOR SMALL ARGUMENT EXPONENTIALS ECN=-GCA/100.0 DO 7 I=1,102 VAL=(I-1)*ECN EXT(I)=EXP(VAL) 7 CONTINUE C ZERO ARRAYS FOR GRIDDED DATA NRNC=NR*NC DO 6 I=1,NRNC C***GUESS MOD IF(IGUESS.EQ.0) XGA(I)=0.0 C*** XGD(I)=0.0 6 XGE(I)=0.0 C GET MULTIPLY COEFFICIENTS FROM EXPONENTS. THESE ARE FOR FILTER ALONG C LINES OF LONGITUDE ( COLUMNS ) EBC=EXP(-BC) EGC=EXP(-GC) EBCA=EXP(-BCA) EGCA=EXP(-GCA) C TWO PASSES, 1-INITIAL INTERPOLATION, 2-CORRECTION DO 100 IPASS=1,2 C SCAN DATA, 1-DECREASING LATITUDE, 2- INCREASING LATITUDE DO 99 IUD=1,2 IF(IUD .EQ. 2) GO TO 8 JLO=0 JINC=1 FLAT=(XLATN+XINC) FLINC=-XINC GO TO 9 8 JLO=NR+1 JINC=-1 FLAT=(XLATN-XINC*NR) FLINC=XINC C ***** ***** 9 CONTINUE C ZERO RUNNING VERTICAL SUMS DO 10 I=1,NC DBA(I)=0.0 DGA(I)=0.0 10 CONTINUE IF(IPASS .EQ. 2) GO TO 12 DO 11 I=1,NC DBD(I)=0.0 DBE(I)=0.0 DGD(I)=0.0 11 DGE(I)=0.0 12 CONTINUE J=JLO C VERTICAL SCAN LOOP DO 98 JJ=1,NR J=J+JINC JHUN=J*100 C ADJUST EXPONENTS AND MULTIPLIERS FOR LATITUDE DEPENDENT DISTANCE C DISTORTIONS. THESE ARE FOR FILTERING ALONG LINES OF LATITUDE ( ROWS ) FLAT=FLAT+FLINC C C--- PREVENT ROUND OFF ERROR AND ASSURE THAT COS(90) = 0 C IF(ABS(FLAT) .EQ. 90.) THEN CL = 0.0 ELSE CL=COS(FLAT*DEG2RAD) ENDIF IF(CL .LT. 0.0) GO TO 999 BR=BC*CL GR=GC*CL BRA=BCA*CL GRA=GCA*CL BRF=BCF*CL GRF=GCF*CL BRAF=BCAF*CL GRAF=GCAF*CL EBR=EXP(-BR) EGR=EXP(-GR) EBRA=EXP(-BRA) EGRA=EXP(-GRA) C DECAY VERTICAL RUNNING SUMS DO 13 I=1,NC DBA(I)=EBC*DBA(I) DGA(I)=EGC*DGA(I) 13 CONTINUE IF(IPASS .EQ. 2) GO TO 15 DO 14 I=1,NC DBD(I)=EBC*DBD(I) DGD(I)=EGC*DGD(I) DBE(I)=EBCA*DBE(I) 14 DGE(I)=EGCA*DGE(I) 15 CONTINUE C SCAN DATA, 1-INCREASING LONGITUDE, 2-DECREASING LONGITUDE DO 97 IRL=1,2 IF(IRL .EQ. 2) GO TO 16 ILO=0 IINC=1 GO TO 17 16 ILO=NC+1 IINC=-1 17 CONTINUE C ZERO RUNNING HORIZONTAL SUMS HBBA=0.0 HBGA=0.0 HGBA=0.0 HGGA=0.0 IF(IPASS .EQ. 2) GO TO 18 HBBD=0.0 HBBE=0.0 HBGD=0.0 HBGE=0.0 HGBD=0.0 HGBE=0.0 HGGD=0.0 HGGE=0.0 18 CONTINUE C INITIALIZE POINTERS INTO STATION GROUP AT THIS LATITUDE IS=J+IUD-1 IR=3-2*IRL IC=3-2*IUD KSTAR=J+IUD+IRL-2 LSTAR=J+IUD-IRL+1 KSTA=IST(KSTAR)+1-IRL LSTA=IST(LSTAR)-2+IRL IJ=J+NR*(ILO-1) IJINC=IINC*NR I=ILO C HORIZONTAL SCAN LOOP DO 96 II=1,NC I=I+IINC IHUN=I*100 IJ=IJ+IJINC C DECAY HORIZONTAL SUMS HBBA=EBR*HBBA HBGA=EGR*HBGA HGBA=EBR*HGBA HGGA=EGR*HGGA IF(IPASS .EQ. 2) GO TO 19 HBBD=EBR*HBBD HBBE=EBRA*HBBE HBGD=EGR*HBGD HBGE=EGRA*HBGE HGBD=EBR*HGBD HGBE=EBRA*HGBE HGGD=EGR*HGGD HGGE=EGRA*HGGE 19 CONTINUE C START OF LOOP TO FIND ALL STATIONS IN THIS GRID BOX, ADJUST C OBSERVATION VALUES BY EXPONENT LOOK UP TABLE, AND ADD VALUES TO C HORIZONTAL RUNNING SUMS 24 IF(IR*(KSTA-LSTA) .GT. 0) GO TO 25 NU=IR*(IHUN-100*XCOL(KSTA)) IF(NU .LT. 0) GO TO 25 MV=IC*(JHUN-100*XROW(KSTA)) IF(MV .GT. 0) GO TO 40 KSTA=KSTA+IR GO TO 24 40 CONTINUE C SCALE FOR DISTANCE FROM STATION TO GRID POINT CBCMV=BCF*MV CGCMV=GCF*MV CBRNU=BRF*NU CGRNU=GRF*NU C CHECK IF LOOKUP TABLE CAN BE USED IF(MV .GE. 100) GO TO 20 IF(NU .GE. 100) GO TO 20 CGBC=CGCMV-CBCMV CGBR=CGRNU-CBRNU IBC=CBCMV+1.5 IGCC=CGBC+1.5 IBR=CBRNU+1.5 IGR=CGBR+1.5 RBC=EXT(IBC) RGC=EXT(IGCC)*RBC RBR=EXT(IBR) RGR=EXT(IGR)*RBR RBRCL=RBR*CLAMB RBB=RBC*RBRCL RBG=RBC*RGR RGB=RGC*RBRCL RGG=RGC*RGR GO TO 21 20 RBB=(CBCMV+CBRNU)*ECN RBG=(CBCMV+CGRNU)*ECN RGB=(CGCMV+CBRNU)*ECN RGG=(CGCMV+CGRNU)*ECN RBB=EXP(RBB)*CLAMB RBG=EXP(RBG) RGB=EXP(RGB)*CLAMB RGG=EXP(RGG) 21 SA=XDA(KSTA) KSTA=KSTA+IR C ADD VALUES TO HORIZONTAL RUNNING SUMS HBBA=HBBA+RBB*SA HBGA=HBGA+RBG*SA HGBA=HGBA+RGB*SA HGGA=HGGA+RGG*SA IF(IPASS .EQ. 2) GO TO 24 HBBD=HBBD+RBB HBGD=HBGD+RBG HGBD=HGBD+RGB HGGD=HGGD+RGG CBCMV=BCAF*MV CGCMV=GCAF*MV CBRNU=BRAF*NU CGRNU=GRAF*NU IF(MV .GE. 100) GO TO 22 IF(NU .GE. 100) GO TO 22 CGBC=CGCMV-CBCMV CGBR=CGRNU-CBRNU IBC=CBCMV+1.5 IGCC=CGBC+1.5 IBR=CBRNU+1.5 IGR=CGBR+1.5 RBC=EXT(IBC) RGC=EXT(IGCC)*RBC RBR=EXT(IBR) RGR=EXT(IGR)*RBR RBRCL=RBR*CLAMB RBB=RBC*RBRCL RBG=RBC*RGR RGB=RGC*RBRCL RGG=RGC*RGR GO TO 23 22 RBB=(CBCMV+CBRNU)*ECN RBG=(CBCMV+CGRNU)*ECN RGB=(CGCMV+CBRNU)*ECN RGG=(CGCMV+CGRNU)*ECN RBB=EXP(RBB)*CLAMB RBG=EXP(RBG) RGB=EXP(RGB)*CLAMB RGG=EXP(RGG) 23 HBBE=HBBE+RBB HBGE=HBGE+RBG HGBE=HGBE+RGB HGGE=HGGE+RGG GO TO 24 C END OF LOOP FOR STATIONS IN A GRID BOX 25 CONTINUE C ADD HORIZONTAL SUMS TO RUNNING VERTICAL SUMS DBA(I)=DBA(I)+CLAMB*(HBBA-HBGA) DGA(I)=DGA(I)+HGBA-HGGA IF(IPASS .EQ. 2) GO TO 26 DBD(I)=DBD(I)+CLAMB*(HBBD-HBGD) DBE(I)=DBE(I)+CLAMB*(HBBE-HBGE) DGD(I)=DGD(I)+HGBD-HGGD DGE(I)=DGE(I)+HGBE-HGGE 26 CONTINUE 96 CONTINUE 97 CONTINUE C ADD VERTICAL SUMS TO GRID ARRAYS IJ=J-NR IF(IPASS .EQ. 2) GO TO 60 DO 61 I=1,NC IJ=IJ+NR XGD(IJ)=XGD(IJ)+(DBD(I)-DGD(I)) XGE(IJ)=XGE(IJ)+(DBE(I)-DGE(I)) 61 CONTINUE C***GUESS MOD IF(IGUESS.NE.0) GO TO 63 IJ=J-NR DO 71 I=1,NC IJ=IJ+NR XGA(IJ)=XGA(IJ)+DBA(I)-DGA(I) 71 CONTINUE C*** GO TO 63 60 CONTINUE DO 62 I=1,NC IJ=IJ+NR IF(XGE(IJ).GT.0.0) THEN EFACT=1./XGE(IJ) XGA(IJ)=XGA(IJ)+(DBA(I)-DGA(I))*EFACT ELSE XGA(IJ)=1.E35 ENDIF 62 CONTINUE 63 CONTINUE 98 CONTINUE 99 CONTINUE IF(IPASS .EQ. 2) GO TO 100 C ADJUST STATION OBSERVATIONS AFTER FIRST PASS FOR ERROR ADJUSTMENT C CALCULATION ON SECOND PASS BC=BCA GC=GCA BCF=BCAF GCF=GCAF EBC=EBCA EGC=EGCA DO 28 I=1,NRNC IF(XGD(I).LE.1.E-20) XGD(I)=-99. IF(XGE(I).LE.1.E-20) XGE(I)=-99. 28 CONTINUE C***GUESS MOD IF(IGUESS.NE.0) GO TO 250 DO 29 IJ=1,NRNC IF(XGD(IJ).GT.0) THEN EFACT=1./XGD(IJ) XGA(IJ)=XGA(IJ)*EFACT ELSE XGA(IJ)=1.E35 ENDIF 29 CONTINUE 250 CONTINUE IL=100 IH=100*NC JL=100 JH=100*NR DO 30 N=1,NSTA I=NINT(XCOL(N)) J=NINT(XROW(N)) IF(I .LT. 1) I=1 IF(I .GT. NC) I=NC IF(J .LT. 1) J=1 IF(J .GT. NR) J=NR IJ=J+NR*(I-1) XDA(N)=XDA(N)-XGA(IJ) 30 CONTINUE 100 CONTINUE RETURN 999 CONTINUE C **** output error message here for: 'FBARN CALLED WITH BAD PARAMETERS' **** CALL ABORT(0) RETURN END C SUBROUTINE HEAPFY(XDA,XROW,XCOL,LL,K) C $ CALL HEAPFY(XDA, XROW, XCOL, LL, K) (WLH) C $ REORDER ELEMENTS OF HEAP AS PART OF HEAP SORT C $ XDA =(R) ARRAY IDA(NSTA) CONTAINING FIRST OBSERVED PARAMETER C $ XROW = (R) ARRAY XROW(NCOL) CONTAINING LATITUDES OF OBSERVATIONS C $ XCOL = (R) ARRAY XCOL(NSTA) CONTAINING LONGITUDES OF OBSERVATIONS C $ LL = (I) INPUT STARTING LOCATION IN HEAP FOR REORDERING C $ K = (I) INPUT ENDING LOCATION IN HEAP FOR REORDER C $$ HEAPFY = OBSERVATION, GRID, COMPUTATION DIMENSION XDA(*),XROW(*),XCOL(*) IFLAG=0 I=LL 4 M=I + I IF(M .GT. K) RETURN N=M+1 IF(ICOMP(XROW,XCOL,I,M) .EQ. 1) GO TO 2 IF(N .GT. K) GO TO 3 IF(ICOMP(XROW,XCOL,M,N) .EQ. 1) GO TO 3 J=N GO TO 1 3 J=M GO TO 1 2 IF(N .GT. K) RETURN IF(ICOMP(XROW,XCOL,I,N) .EQ. 1) RETURN J=N GO TO 1 ENTRY INTER(XDA,XROW,XCOL,LL,K) C $ ENTRY INTER(XDA, XROW, XCOL, LL, K) (WLH) C $ INTERCHANGES (SWAPS) POSITIONS OF VECTORS C $ XDA =(R) ARRAY IDA(NSTA) CONTAINING FIRST OBSERVED PARAMETER C $ XROW = (R) ARRAY XROW(NCOL) CONTAINING LATITUDES OF OBSERVATIONS C $ XCOL = (R) ARRAY XCOL(NSTA) CONTAINING LONGITUDES OF OBSERVATIONS C $ LL = (I) INPUT STARTING LOCATION IN HEAP FOR REORDERING C $ K = (I) INPUT ENDING LOCATION IN HEAP FOR REORDER C $$ INTER = OBSERVATION, GRID, COMPUTATION IFLAG=1 I=LL J=K 1 X=XDA(I) XDA(I)=XDA(J) XDA(J)=X X=XROW(I) XROW(I)=XROW(J) XROW(J)=X X=XCOL(I) XCOL(I)=XCOL(J) XCOL(J)=X IF(IFLAG .EQ. 1) RETURN I=J GO TO 4 END C FUNCTION ICOMP(XROW,XCOL,I,J) C $ ICOMP(XROW, XCOL, I, J) (WLH) C $ PERFORMS LEXICAL COMPARISON OF 2 (LAT,LON) VECTORS C $ XROW = (R) ARRAY XROW(NCOL) CONTAINING LATITUDES OF OBSERVATIONS C $ XCOL = (R) ARRAY XCOL(NSTA) CONTAINING LONGITUDES OF OBSERVATIONS C $ I = (I) INPUT INDEX OF FIRST VECTOR FOR COMPARE C $ J = (I) INPUT INDEX OF SECOND VECTOR FOR COMPARE C $$ ICOMP = OBSERVATION, GRID, COMPUTATION COMMON/CONS/NRP DIMENSION XROW(*),XCOL(*) K=XROW(I)+1 IF(K .LT. 1) K=1 IF(K .GT. NRP) K=NRP L=XROW(J)+1 IF(L .LT. 1) L=1 IF(L .GT. NRP) L=NRP IF(K .LT. L) GO TO 1 IF(K .GT. L) GO TO 2 IF(XCOL(I) .LE. XCOL(J)) GO TO 1 2 ICOMP=1 RETURN 1 ICOMP=0 RETURN END .