Document title: Fortran subroutine OAREAD to be used in program OAWATSREAD Project: DE NDADS Datatype: WATS_2S_ASCII EID: SOFTWARE Super-EID: SOFTWARE There may be other documents also identified by this super-EID. NDADS filename: wats_oaread_de.for TRF entry: b47609.for in NSSDC's controlled digital document library, Dec. 1998. Document text follows: ---------------------- C--------------------------------------------------------- C C To read the 4 minute data in SYS$OA:OABASE.DAT C C OAREAD Simulation for single record return C A. E. Hedin 11/20/84 C End of day correction 3/8/85 C Modified for 4 minute data set 7/5/85 (S.Cohn) C C Input parameters: C C IDATE - Date of data (YYDDD). C ITIME - Time of data (Millisec). C MAP - Array containing number of required parameters C plus list of parameters (as on Sigma 9) C 13 Orbit number C 32 Altitude C 33 Latitude C 34 Longitude C 37 Local Solar Time C 38 Local Magnetic Time C 39 L Shell C 40 Invariant Latitude C 76 Solar Zenith Angle C C Output parameters: C C IERR - Error return from file open C ierr = -20 means gap in data prevented interpolation (may not occur) C ierr = -21 means read error from OABASE.DAT (probably C trying to access non-existant record) C DATA - Array of data according to MAP C C I/O Unit 79 for input. C C-------------------------------------------------------------------- SUBROUTINE OAREAD(IDATE,ITIME,IERR,MAP,DATA) PARAMETER LATITUDE = 2 ! D(2,*) ARE THE LATITUDES. INTEGER*2 IDATA2(8) INTEGER MAP(1), MO(76), ITIM(4), JPTS(4), ZPTS(4), IPTS(4) INTEGER ITPOLE, J, K, L, NALT, NSZA, NIL REAL DATA(1), D(9,4), ADD(9), DELTA, DT, DIFFL, DATAIL LOGICAL FIRST, TIMLOG DATA MO/12*0,9,0,17*0,1,2,3,0,0,5,8,7,6,35*0,4/ DATA IDATEL/0/, ITIM1,ITIM2/-100000,-100000/ DATA ITFDIF/60000/, ERROUT/-999./, ERRIN/9000./, IDITO/-99999/ DATA ADD/999.,999.,90.,999.,6.,999.,999.,6.,999./ DATA FIRST/.TRUE./, IPTS,JPTS,ZPTS/12*0/, DATAIL/-999./ IERR=0 JUMPKEY=0 C Open file for new date IF(FIRST) THEN FIRST=.FALSE. OPEN(UNIT=79,NAME='OABASE.DAT',TYPE='OLD', & ACCESS='KEYED',KEY=(1:4:INTEGER),READONLY, & RECL=6,FORM='UNFORMATTED',ORGANIZATION='INDEXED', & SHARED) ENDIF C Get FOUR records around requested time ITIMEB = ITIME ID = (IDATE-80000) IT = (INT(ITIMEB/240000) - 1)*240 !the -1 for new quadratic fit IF((IT*1000+240000) .EQ. ITIME) THEN TIMLOG=.TRUE. ELSE TIMLOG=.FALSE. ENDIF IGAPSIZE=120000 IBIGDIFFO=240001 IBIGDIFFE=240001 IF(IT .LT. 0) THEN !Previous day IT = 86400 + IT ITIMEB = ITIMEB + 86400000 IDM = IFIX(ID*.001)*1000 IF(ID .EQ. IDM+1) THEN ID = IDM + 365 - 1000 ELSE ID = ID - 1 ENDIF ENDIF IDIT=ID*100000+IT IF(IDIT .EQ. IDITO) GOTO 133 !Same times IDITO = IDIT C Input records contain: 1)altitude, 2) latitude, 3) longitude, C 4) Solar Zenith Angle, 5) Local solar time, 6) Invariant lat, C 7) L shell, 8) Local magnetic time, 9) Orbit number. NALT=0 !counter for number of OK alt points NSZA=0 !counter for number of OK SZA points NIL=0 !counter for number of OK Inv_Lat points NEAREST=0 !index of nearest point for ORBIT choice READ(79,ERR=89,KEYEQ=IDIT) IDIT1, (IDATA2(K),K=1,8), IORB ITIME1=IDIT1/100000 ITIM(1)=(IDIT1-ITIME1*100000) * 1000 IF(ABS(ITIMEB-ITIM(1)) .LE. igapsize) NEAREST=1 DO L = 1, 8 D(L,1) = FLOAT(IDATA2(L))*.1 ENDDO D(9,1) = FLOAT(IORB)*.1 IF(D(1,1) .LT. ERRIN) THEN !alt NALT = NALT + 1 JPTS(NALT)=1 ENDIF IF(D(4,1) .LT. ERRIN) THEN NSZA = NSZA + 1 ZPTS(NSZA)=1 ENDIF IF(D(6,1) .LT. ERRIN) THEN !IL C Adjustment for bad data due to pole crossing IF((D(6,1) .EQ. -999.) .AND. & (ABS(D(LATITUDE,1)) .GT. 45)) THEN D(6,1)=87.5 ENDIF IF(D(6,1) .NE. -999.) THEN !not bad data NIL = NIL + 1 IPTS(NIL)=1 ENDIF ENDIF c Now sequential read READ(79) IDIT2, (IDATA2(K), K = 1, 8), IORB ITIME2=IDIT2/100000 ITIM(2)=(IDIT2-ITIME2*100000) * 1000 IF(ITIME1 .EQ. ITIME2) THEN CONTINUE ELSEIF(ITIME1 .EQ. ITIME2 - 1) THEN ITIM(2) = ITIM(2) + 86400000 JUMPKEY=1 ELSEIF(((ITIME1+636) .EQ. ITIME2) .AND. & mod(ITIME2,1000) .EQ. 1) THEN !Yr Jump ITIM(2) = ITIM(2) + 86400000 JUMPKEY=1 ELSE IOS=-20 GOTO 90 ENDIF IF(ABS(ITIMEB-ITIM(2)) .LE. IGAPSIZE) NEAREST=2 IF((ITIM(2) - ITIM(1)) .GT. IBIGDIFFE) THEN IOS=-20 GOTO 90 ENDIF DO L = 1, 8 D(L,2) = FLOAT(IDATA2(L))*.1 ENDDO D(9,2) = FLOAT(IORB)*.1 IF(D(1,2) .LT. ERRIN) THEN NALT = NALT + 1 JPTS(NALT)=2 ENDIF IF(D(4,2) .LT. ERRIN) THEN NSZA = NSZA + 1 ZPTS(NSZA)=2 ENDIF IF(D(6,2) .LT. ERRIN) THEN !IL C Adjustment for bad data due to pole crossing IF((D(6,2) .EQ. -999.) .AND. & (ABS(D(LATITUDE,2)) .GT. 45)) THEN D(6,2)=87.5 ENDIF IF(D(6,2) .NE. -999.) THEN !not bad data NIL = NIL + 1 IPTS(NIL)=2 ENDIF ENDIF C Third record READ(79) IDIT3, (IDATA2(K), K = 1, 8), IORB ITIME3=IDIT3/100000 ITIM(3)=(IDIT3-ITIME3*100000) * 1000 IF(ITIME2 .EQ. ITIME3) THEN ITIM(3) = ITIM(3) + 86400000 * JUMPKEY ELSEIF(ITIME2 .EQ. ITIME3 - 1) THEN ITIM(3) = ITIM(3) + 86400000 JUMPKEY = 1 ELSEIF(((ITIME2+636) .EQ. ITIME3) .AND. & MOD(ITIME3,1000) .EQ. 1) THEN !Yr Jump ITIM(3) = ITIM(3) + 86400000 JUMPKEY = 1 ELSE IOS=-20 GOTO 90 ENDIF IF(ABS(ITIMEB-ITIM(3)) .LE. IGAPSIZE) NEAREST=3 IF((ITIM(3) - ITIM(2)) .GT. IBIGDIFFO) THEN IOS=-20 GOTO 90 ENDIF DO L = 1, 8 D(L,3) = FLOAT(IDATA2(L))*.1 ENDDO D(9,3) = FLOAT(IORB)*.1 IF(D(1,3) .LT. ERRIN) THEN NALT = NALT + 1 JPTS(NALT)=3 ENDIF IF(D(4,3) .LT. ERRIN) THEN NSZA = NSZA + 1 ZPTS(NSZA)=3 ENDIF IF(D(6,3) .LT. ERRIN) THEN !IL C Adjustment for bad data due to pole crossing IF((D(6,3) .EQ. -999.) .AND. & (ABS(D(LATITUDE,3)) .GT. 45)) THEN D(6,3)=87.5 ENDIF IF(D(6,3) .NE. -999.) THEN !not bad data NIL = NIL + 1 IPTS(NIL)=3 ENDIF ENDIF C Fourth record READ(79) IDIT4, (IDATA2(K), K = 1, 8), IORB ITIME4=IDIT4/100000 ITIM(4)=(IDIT4-ITIME4*100000) * 1000 IF(ITIME3 .EQ. ITIME4) THEN ITIM(4) = ITIM(4) + 86400000 * JUMPKEY ELSEIF(ITIME3 .EQ. ITIME4 - 1) THEN ITIM(4) = ITIM(4) + 86400000 ELSEIF(((ITIME3+636) .EQ. ITIME4) .AND. & MOD(ITIME4,1000) .EQ. 1) THEN !Yr Jump ITIM(4) = ITIM(4) + 86400000 ELSE IOS=-20 GOTO 90 ENDIF IF(ABS(ITIMEB-ITIM(4)) .LE. IGAPSIZE) NEAREST=4 IF((ITIM(4) - ITIM(3)) .GT. IBIGDIFFE) THEN IOS=-20 GOTO 90 ENDIF DO L = 1, 8 D(L,4) = FLOAT(IDATA2(L))*.1 ENDDO D(9,4) = FLOAT(IORB)*.1 IF(D(1,4) .LT. ERRIN) THEN NALT = NALT + 1 JPTS(NALT)=4 ENDIF IF(D(4,4) .LT. ERRIN) THEN NSZA = NSZA + 1 ZPTS(NSZA)=4 ENDIF IF(D(6,4) .LT. ERRIN) THEN !IL C Adjustment for bad data due to pole crossing IF((D(6,4) .EQ. -999.) .AND. & (ABS(D(LATITUDE,4)) .GT. 45)) THEN D(6,4)=87.5 ENDIF IF(D(6,4) .NE. -999.) THEN !not bad data NIL = NIL + 1 IPTS(NIL)=4 ENDIF ENDIF IF(NEAREST .EQ. 0) THEN IOS=-30 GOTO 90 ENDIF 133 DT=FLOAT(ITIM(3)-ITIM(2)) !the size of the middle time interval C Find time of pole crossing ITPOLE=-1 D5=ABS(D(3,3)-D(3,2)) !absolute difference in longitude IF((D5 .GT. ADD(3) .AND. D5 .LT. 3.*ADD(3)) .OR. !>90 long. diff. & ABS(D(2,2)) .EQ. 90. .OR. ABS(D(2,3)) .EQ. 90.) THEN !at the pole IF(D(2,2) .LT. ERRIN .AND. D(2,3) .LT. ERRIN) THEN XPOLE=SIGN(90.,D(2,2)) ITPOLE=DT*(XPOLE-D(2,2))/(2.*XPOLE-D(2,3)-D(2,2))+ITIM(2) ENDIF ENDIF C Interpolate data DELTA=FLOAT(ITIMEB-ITIM(2))/DT !fraction of time interval to ITIMEB DO 20 J=1,MAP(1) K=MO(MAP(J+1)) IF(TIMLOG .OR. K .EQ. 9) THEN !exact time or orbit number IF(K .EQ. 4) THEN !exact time SZA, convert radians to degrees DATA(J)=D(K,NEAREST) ELSE DATA(J)=D(K,NEAREST) !otherwise we interpolate below ENDIF ELSEIF(K .EQ. 6) THEN !find IL IF(D(K,2) .LT. ERRIN .AND. D(K,3) .LT. ERRIN .AND. & D(K,2) .NE. -999 .AND. D(K,3) .NE. -999) THEN !General interp IF(NIL .GT. 2) THEN !Lagrange's quadratic interpolation DATAIL=F_LAGRANGE(ITIM,D,6,ITIMEB,NIL,IPTS) ELSE !linear interpolation C Adjust for crossing a pole and any subsequent wraparound IF(ITPOLE .GT. -1) THEN !pole crossing DATAIL=D(K,2)+DELTA*(180.-D(K,2)-D(K,3)) IF(DATAIL .GT. 90) DATAIL=180.-DATAIL !wraparound ELSE DATAIL=D(K,2)+DELTA*(XU-D(K,2)) ENDIF ENDIF ELSE !Fill data input DATAIL=AMIN1(D(K,2),D(K,3)) !will probably equal -999 here ENDIF DATA(J)=DATAIL ELSEIF(K .EQ. 7) THEN !L Shell IF(DATAIL .NE. -999) THEN !requires that Inlat be earlier in MAP DATA(J)=(1/COS(DATAIL*0.01745329))**2 ELSE !a bad data point in the data base or Inlat not done 1st DATA(J)=DATAIL ENDIF ELSEIF(K .GT. 0 .AND. & D(K,2) .LT. ERRIN .AND. D(K,3) .LT. ERRIN) THEN !no cRaZy data XU=D(K,3) !use this for the end point for linear interpolation C here do altitude fit (K=1) IF(K .EQ. 1) THEN !altitude interpolation IF(NALT .GT. 2) THEN !Lagrange's quadratic interp DATA(J)=F_LAGRANGE(ITIM,D,K,ITIMEB,NALT,JPTS) ELSEIF(NALT .EQ. 2) THEN !linear interpolation DATA(J)=DELTA*(XU-D(K,2))+D(K,2) ELSE !error default value DATA(J)=-999 ENDIF ELSEIF(K .EQ. 2) THEN !linear interpolation of LATITUDE IF(ITPOLE .GT. -1) THEN !polar Xing DATA(J)=D(K,2)+DELTA*(2.*XPOLE-XU-D(K,2)) IF(ABS(DATA(J)) .GT. 90.) DATA(J)=2.*XPOLE-DATA(J) ELSE !not a polar Xing DATA(J)=D(K,2)+DELTA*(XU-D(K,2)) ENDIF ELSEIF(K .EQ. 3 .AND. ITPOLE .EQ. -1) THEN !LONG., no pole Xing IF(XU*D(K,2) .LT. 0.) THEN !crosses zero degrees long.? DIFFL=ABS(XU-D(K,2)) IF(DIFFL .GT. 180.) THEN !probably Xes +/-180 long. instead IF(D(K,2) .LT. 0.) THEN DATA(J)=D(K,2)-DELTA*(360-DIFFL) !use adjusted DIFFL IF(DATA(J) .LT. -180.) DATA(J)=DATA(J)+360. ELSE !D(K,2)>0. DATA(J)=D(K,2)+DELTA*(360-DIFFL) !use adjusted DIFFL IF(DATA(J) .GT. 180.) DATA(J)=DATA(J)-360. ENDIF ELSE !zero degree crossing (Xing) DATA(J)=D(K,2)+DELTA*(XU-D(K,2)) ENDIF ELSE !treat as normal DATA(J)=D(K,2)+DELTA*(XU-D(K,2)) ENDIF ELSEIF(K .EQ. 4) THEN !SZA IF(NSZA .GT. 2) THEN !quadratic interpolation DATA(J)=F_LAGRANGE(ITIM,D,K,ITIMEB,NSZA,ZPTS) ELSEIF(NSZA .EQ. 2) THEN !linear interpolation DATA(J)=D(K,2)+DELTA*(D(K,3)-D(K,2)) ELSE !error default value DATA(J)=-999 ENDIF C Here get LST when not crossing a pole or LMT ELSEIF((K .EQ. 5 .AND. ITPOLE .EQ. -1) .OR. K .EQ. 8) THEN DIFFL=ABS(XU-D(K,2)) IF(DIFFL .GT. 12.) THEN !probably crosses 24/0 hours IF(D(K,2) .LT. 12.) THEN DATA(J)=D(K,2)-DELTA*(24.-DIFFL) !use adjusted DIFFL IF(DATA(J) .LT. 0.) DATA(J)=DATA(J)+24. ELSE !D(K,2)>12. DATA(J)=D(K,2)+DELTA*(24.-DIFFL) !use adjusted DIFFL IF(DATA(J) .GT. 24.) DATA(J)=DATA(J)-24. ENDIF ELSE !doesn't cross LS or LM midnight DATA(J)=D(K,2)+DELTA*(XU-D(K,2)) ENDIF C At a polar crossing event, we presume that LONG and LST don't C change slowly enough to interpolate and will have the same value as the C recorded data (D(K,i)) before or after the pole crossing, as determined C by comparing the time we're interpolating (ITIMEB) vs. the time of C crossing (ITPOLE) ELSEIF((K .EQ. 3 .OR. K .EQ. 5) .AND. & ITPOLE .GT. -1) THEN IF(ITIMEB .GE. ITPOLE) THEN !if near but past pole DATA(J)=D(K,3) ELSE !not past pole yet DATA(J)=D(K,2) ENDIF ELSE DATA(J)=ERROUT ENDIF !of "IF(K .EQ. 1..." ELSE DATA(J)=ERROUT ENDIF !of "IF(TIMLOG..." 20 ENDDO RETURN C Error exit 89 IOS=-21 90 IERR=IOS DO J=1,MAP(1) DATA(J)=ERROUT ENDDO RETURN END CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC C Function to interpolate ALTITUDE from 3 or 4 points. C For use with OAREAD4 FUNCTION F_LAGRANGE(ITIM,D,K,ITIMEB,NUM,JPTS) DIMENSION ITIM(4),D(9,4),JPTS(4) REAL*8 Li,A F_LAGRANGE = 0. T0 = FLOAT(ITIMEB) DO I=1,NUM A = D(K,JPTS(I)) Ti = FLOAT(ITIM(JPTS(I))) Li = 1. DO J=1,NUM T = FLOAT(ITIM(JPTS(J))) IF( I.ne.J ) Li = Li * (T0-T)/(Ti-T) ENDDO F_LAGRANGE = F_LAGRANGE + A*Li ENDDO RETURN END