! gethahn.f90 ! program written by Tim Mitchell, Tyndall Centre ! loads the (v large) Hahn data-set and extracts the useful stuff and saves it to CRU ts files ! now does this in a two-pass process, as per Phil Jones email on 22.02.02 ! pass 1: create a clim for each month/hour/stn ! pass 2: calc anoms, av 2+ anom --> day, av 20+ days --> month ! now calcs wind direction properly ! written 13.02.02 ! last modified 25.04.02 ! pgf90 -Mstandard -Minfo -fast -Mscalarsse -Mvect=sse -Mflushz ! f90 -o ./../obs/gethahn time.f90 filenames.f90 crutsfiles.f90 wmokey.f90 ./../obs/gethahn.f90 program GetHahn use Time use FileNames use CRUtsFiles use WMOKey implicit none integer, parameter :: QPass = 1 !@@@@@@@@@@@@@@@@@@ set to either 1 or 2 @@@@@@@@@@@@@@@@@ integer, parameter :: ThreshClim = 150 ! min values to set a climatology (rec=?) integer, parameter :: ThreshDay = 20 ! min days to calc a month anom (rec=20) integer, parameter :: ThreshHour = 2 ! min hours to calc a day anom (rec=2) integer, parameter :: BegYear = 1971 ! 1971...1996 integer, parameter :: BegMonth = 1 ! 1...12 integer, parameter :: EndYear = 1996 ! 1971...1996 integer, parameter :: EndMonth = 12 ! 1...12 real, pointer, dimension (:,:,:) :: OutOct,OutSLP,OutWnd,OutDir,OutVap,OutTmp,OutWdx,OutWdy,OutAny real, pointer, dimension (:,:,:) :: ClimOct,ClimSLP,ClimWnd,ClimDir,ClimVap,ClimTmp,ClimWdx,ClimWdy,ClimAny real, pointer, dimension (:) :: Lat,Lon,Elv real, pointer, dimension (:) :: MyLat,MyLon,MyElv real, dimension (8) :: HourMean real, dimension (8) :: InMulti = (/1.00,0.1,0.1,0.1,0.1,0.001,0.001,1.0/) real, dimension (8) :: OutMulti = (/0.01,0.1,0.1,0.1,0.1,0.001,0.001,0.1/) integer, pointer, dimension (:,:,:) :: InOct,InSLP,InWnd,InDir,InVap,InTmp,InWdx,InWdy,InAny integer, pointer, dimension (:,:,:) :: TotOct,TotSLP,TotWnd,TotDir,TotVap,TotTmp,TotWdx,TotWdy,TotAny integer, pointer, dimension (:,:,:) :: SaveAny,CountStnOut,CountStnTot integer, pointer, dimension (:,:) :: StnInfo,CountStnIn,CountAllIn,MonthLengths integer, pointer, dimension (:) :: Code ! WMO codes (6-digit, size=StnN) integer, pointer, dimension (:) :: YearAD integer, dimension (31) :: DayObs integer, dimension (8) :: HourObs integer, dimension (8) :: InMiss = (/-1,-1,-1,900,900,-999,-999,-1/) character (len=3), dimension (12), parameter :: MonthName=(/'JAN','FEB','MAR','APR','MAY','JUN', & 'JUL','AUG','SEP','OCT','NOV','DEC'/) character (len=80), pointer, dimension (:,:) :: RawFiles character (len=20), pointer, dimension (:) :: MyNameStn,NameStn character (len=13), pointer, dimension (:) :: MyNameCty,NameCty character (len=09), pointer, dimension (:) :: MyNameLoc,NameLoc character (len=04), dimension (8) :: OutSuffices = & (/'.oct','.slp','.wnd','.vap','.tmp','.wdx','.wdy','.dir'/) real, parameter :: Kay1wet = 17.380 real, parameter :: Kay1ice = 22.440 real, parameter :: Kay2wet = 239.000 real, parameter :: Kay2ice = 272.400 real, parameter :: Kay3 = 6.107 real, parameter :: Pi = 3.1415927 real :: OpTot,OpEn, HourTot,HourEn, DayTot,DayEn, MonthClim, Angle real :: Tdry,Tdew,Twet integer :: ReadStatus, AllocStat integer :: NStn,NYear,NMonth,NDay,NHour,NLine,NCode,NHourValid,NDayValid,NVari integer :: XStn,XYear,XMonth,XDay,XHour,XLine,XCode,XHourValid,XDayValid,XVari integer :: PrevDay,PrevHour,PrevCode integer :: QZip integer :: LoadFileLen,HourOpp,WMOCode integer :: IDy,IHr,IIB,ILat,ILon,IID,ICld,ISLP,IWS,IWD,IAT,IDD,IEl integer :: OpMin,OpMax,Hour0,Hour1,HourGap,TrashInt character (len=80) :: RawFormat = "(4x,2i2,i1,3i5,3x,i1,28x,i5,2i3,i4,i3,i4,2x)" character (len=80) :: CodeFile,LoadFile,SaveStem,SaveTip,SaveFile character (len=20) :: YearStr20,BegYearTxt,EndYearTxt character (len=02) :: YearStr02 !******************************************************************************* call Intro call GetCode call GetFilePaths call AllocArrays if (QPass.EQ.2) call LoadSynClim do XYear = 1, NYear do XMonth = 1, NMonth if (RawFiles(XYear,XMonth).NE."blank") then print "(a,a3,x,i4)", " > Operating on ", MonthName(XMonth), YearAD(XYear) call PrepRawFile call StoreIn call ShutRawFile if (QPass.EQ.2) call InToOut if (QPass.EQ.1) call InToClim call DumpYrMonStats end if end do end do call HarmoniseStn if (QPass.EQ.2) then call RestoreAbs call MakeDir call DumpCruTS call DumpOpStats else if (QPass.EQ.1) then call CheckClim call DumpSynClim call DumpClimStats end if call Conclude contains !******************************************************************************* subroutine Intro open (99,file="/tyn1/tim/scratch/log-gethahn.dat",status="replace",action="write") print* print*, " > ***** GetHahn.f90: loads Hahn data files and saves to CRU ts *****" print* end subroutine Intro !******************************************************************************* ! these codes are 5-digit WMO codes subroutine GetCode CodeFile = "/tyn1/tim/data/obs/hahn/ystaty.txt" open (1,file=CodeFile,status="old",action="read") read (1,"(i6)"), NStn allocate (Code(NStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GetCode: Allocation failure #####" do XStn = 1, NStn read (1,"(i5)"), Code(XStn) end do close (1) end subroutine GetCode !******************************************************************************* subroutine GetFilePaths NYear = EndYear - BegYear + 1 NMonth = 12 ; NDay = 31 ; NHour = 8 ; NVari = 8 allocate (RawFiles(NYear,NMonth), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GetFilePaths: Allocation failure: RawFiles* #####" RawFiles = "blank" XYear = 1 ; XMonth = BegMonth do YearStr20 = GetTextFromInt (BegYear+XYear-1) YearStr02 = trim(adjustl(YearStr20(3:4))) do RawFiles(XYear,XMonth) = "/tyn1/tim/data/obs/hahn/_raw/" // MonthName(XMonth) // YearStr02 // "L" XMonth = XMonth + 1 if (XYear.EQ.NYear.AND.XMonth.GT.EndMonth) exit if (XMonth.GT.NMonth) exit end do XMonth = 1 XYear = XYear + 1 if (XYear.GT.NYear) exit end do end subroutine GetFilePaths !******************************************************************************* subroutine AllocArrays allocate (InOct(NDay,NHour,NStn), & ! for initi see PrepRawFile InSLP(NDay,NHour,NStn), & InWdx(NDay,NHour,NStn), & InWdy(NDay,NHour,NStn), & InWnd(NDay,NHour,NStn), & InVap(NDay,NHour,NStn), & InTmp(NDay,NHour,NStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocArrays: Allocation failure: In* #####" allocate (ClimOct(NMonth,NHour,NStn), & ClimSLP(NMonth,NHour,NStn), & ClimWdx(NMonth,NHour,NStn), & ClimWdy(NMonth,NHour,NStn), & ClimWnd(NMonth,NHour,NStn), & ClimVap(NMonth,NHour,NStn), & ClimTmp(NMonth,NHour,NStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocArrays: Allocation failure: Clim* #####" ClimOct=-9999 ; ClimSLP=-9999 ; ClimWnd=-9999 ; ClimVap=-9999 ; ClimTmp=-9999 ClimWdx=-9999 ; ClimWdy=-9999 if (QPass.EQ.2) then allocate (OutOct(NYear,NMonth,NStn), & OutSLP(NYear,NMonth,NStn), & OutWdx(NYear,NMonth,NStn), & OutWdy(NYear,NMonth,NStn), & OutWnd(NYear,NMonth,NStn), & OutDir(NYear,NMonth,NStn), & OutVap(NYear,NMonth,NStn), & OutTmp(NYear,NMonth,NStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocArrays: Allocation failure: Out* #####" OutOct=-9999 ; OutSLP=-9999 ; OutWnd=-9999 ; OutDir=-9999 ; OutVap=-9999 ; OutTmp=-9999 OutWdx=-9999 ; OutWdy=-9999 else if (QPass.EQ.1) then allocate (TotOct(NMonth,NHour,NStn), & TotSLP(NMonth,NHour,NStn), & TotWdx(NMonth,NHour,NStn), & TotWdy(NMonth,NHour,NStn), & TotWnd(NMonth,NHour,NStn), & TotVap(NMonth,NHour,NStn), & TotTmp(NMonth,NHour,NStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocArrays: Allocation failure: Tot* #####" TotOct=0 ; TotSLP=0 ; TotWdx=0 ; TotWdy=0 ; TotWnd=0 ; TotVap=0 ; TotTmp=0 end if allocate (Lat(NStn), & Lon(NStn), & Elv(NStn), & NameStn(NStn), & NameCty(NStn), & NameLoc(NStn),stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocArrays: Allocation failure: Stn* #####" Lat=-999.0 ; Lon=-999.0 ; Elv=-999.0 ; NameStn="" ; NameCty="unidentified" ; NameLoc=" nocode" allocate (CountAllIn (NYear,NMonth), & CountStnIn (NDay,NHour), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocArrays: Allocation failure: Count* #####" CountAllIn = 0 ; CountStnIn = 0 if (QPass.EQ.2) then allocate (CountStnOut(NYear,NMonth,NVari), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocArrays: Allocation failure: CountStnOut #####" CountStnOut = 0 else if (QPass.EQ.1) then allocate (CountStnTot(NMonth,NHour,NVari), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocArrays: Allocation failure: CountStnTot #####" CountStnTot = 0 end if allocate (YearAD(NYear),MonthLengths(NYear,NMonth), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AllocArrays: Allocation failure: YearAD #####" do XYear = 1, NYear YearAD(XYear) = BegYear + XYear - 1 end do call GetMonthLengths (YearAD,MonthLengths) end subroutine AllocArrays !******************************************************************************* subroutine PrepRawFile InOct=-999 ; InSLP=-999 ; InWdx=-999 ; InWdy=-999 ; InWnd=-999 ; InVap=-999 ; InTmp=-999 LoadFile = LoadPath(RawFiles(XYear,XMonth)," ") LoadFileLen = len_trim(LoadFile) if (LoadFileLen.GT.1.AND.LoadFile((LoadFileLen-1):LoadFileLen).EQ.".Z") then QZip = 2 ! file is zipped call system ('uncompress ' // LoadFile) LoadFile ((LoadFileLen-1):LoadFileLen) = " " ! change filename to the unzipped file else QZip = 1 ! file already unzipped end if call system ('wc -l ' // LoadFile // ' > trashme-prf.txt') ! get number of lines open (3,file='trashme-prf.txt',status="old",access="sequential",form="formatted",action="read") read (3,"(i8)"), NLine close (3) call system ('rm trashme-prf.txt') end subroutine PrepRawFile !******************************************************************************* subroutine StoreIn CountStnIn = 0 ; PrevCode = 0 ; PrevDay = 0 ; PrevHour = 0 open (1,file=LoadFile,status="old",action="read") do XLine = 1, NLine read (1,RawFormat), IDy,IHr,IIB,ILat,ILon,IID,ICld,ISLP,IWS,IWD,IAT,IDD,IEl XDay = IDy ; XHour = (IHr/3)+1 ; WMOCode = IID ; XStn = -999 ; XCode = PrevCode if (PrevDay.NE.XDay.OR.PrevHour.NE.XHour.OR.WMOCode.LT.Code(PrevCode)) XCode = 0 do ! find station XCode = XCode + 1 if (WMOCode.EQ.Code(XCode)) then PrevCode = XCode XStn = XCode end if if (WMOCode.LT.Code(XCode)) exit if (XCode.EQ.NStn) exit if (XStn.NE.-999) exit end do PrevDay = XDay ; PrevHour = XHour if (XStn.NE.-999) then CountStnIn(XDay,XHour) = CountStnIn(XDay,XHour) + 1 if (IDD.NE.700.AND.IDD.NE.900.AND.IAT.NE.900) then Tdry = real(IAT) * 0.1 Tdew = Tdry - (real(IDD) * 0.1) Twet = (0.6 * Tdew) + (0.4 * Tdry) if (Twet.GE.0) then InVap(XDay,XHour,XStn) = nint(10 * Kay3 * exp((Kay1wet * Tdew) / (Kay2wet + Tdew))) else InVap(XDay,XHour,XStn) = nint(10 * Kay3 * exp((Kay1ice * Tdew) / (Kay2ice + Tdew))) end if end if InSLP(XDay,XHour,XStn)=ISLP InTmp(XDay,XHour,XStn)=IAT if (IIB.EQ. 1) InOct(XDay,XHour,XStn)=ICld if (IWS.NE.999) InWnd(XDay,XHour,XStn)=IWS if (IWD.GE.0.AND.IWD.LE.360) then InWdx(XDay,XHour,XStn) = nint(1000 * sin(real(IWD)*Pi/180.0)) InWdy(XDay,XHour,XStn) = nint(1000 * cos(real(IWD)*Pi/180.0)) end if if (Elv(XStn).EQ.-999) then Lat(XStn)=real(ILat)/100.0 ; Lon(XStn)=real(ILon)/100.0 ; Elv(XStn)=real(IEl) if (Lon(XStn).GT.180.0) Lon(XStn) = Lon(XStn) - 360.0 end if end if end do close (1) end subroutine StoreIn !******************************************************************************* subroutine ShutRawFile if (QZip.EQ.2) call system ('compress ' // LoadFile // ' &') end subroutine ShutRawFile !******************************************************************************* subroutine InToClim do XVari = 1, 7 ! iterate by variable call SelectArraysIn ; call SelectArraysClim ; call SelectArraysTot do XStn = 1, NStn ! iterate by station do XHour = 1, NHour ! iterate by hour HourTot = 0.0 ; HourEn = 0.0 do XDay = 1, NDay ! check for datum if (InAny(XDay,XHour,XStn).NE.InMiss(XVari).AND.InAny(XDay,XHour,XStn).NE.-999) then HourEn = HourEn + 1.0 HourTot = HourTot + (InAny(XDay,XHour,XStn) * InMulti(XVari)) end if end do if (HourEn.GT.0) then ! if valid data if (TotAny(XMonth,XHour,XStn).EQ.0) then ! if no previous data ClimAny(XMonth,XHour,XStn) = HourTot/HourEn TotAny(XMonth,XHour,XStn) = nint(HourEn) else ! else update average ClimAny(XMonth,XHour,XStn) = ((ClimAny(XMonth,XHour,XStn)*real(TotAny(XMonth,XHour,XStn))) & +HourTot)/(real(TotAny(XMonth,XHour,XStn))+HourEn) TotAny(XMonth,XHour,XStn) = TotAny(XMonth,XHour,XStn) + nint(HourEn) end if end if end do end do nullify(InAny,TotAny,ClimAny) end do end subroutine InToClim !******************************************************************************* subroutine InToOut do XVari = 1, 7 ! iterate by variable call SelectArraysIn ; call SelectArraysClim ; call SelectArraysOut do XStn = 1, NStn ! iterate by station DayTot = 0.0 ; DayEn = 0.0 do XDay = 1, NDay ! iterate by day HourTot = 0.0 ; HourEn = 0.0 do XHour = 1, NHour ! iterate by hour if (ClimAny(XMonth,XHour,XStn).NE.-9999) then ! check for clim if (InAny(XDay,XHour,XStn).NE.InMiss(XVari).AND.InAny(XDay,XHour,XStn).NE.-999) then HourEn = HourEn + 1.0 HourTot = HourTot + ((InAny(XDay,XHour,XStn)*InMulti(XVari)) - ClimAny(XMonth,XHour,XStn)) end if end if end do if (HourEn.GE.ThreshHour) then DayEn = DayEn + 1.0 DayTot = DayTot + (HourTot / HourEn) end if end do if (DayEn.GE.ThreshDay) OutAny(XYear,XMonth,XStn) = DayTot / DayEn end do nullify(InAny,OutAny,ClimAny) end do end subroutine InToOut !******************************************************************************* subroutine HarmoniseStn call GetCRUtsInfo (Code,MyLat,MyLon,MyElv,MyNameStn,MyNameCty,Digits=5) do XStn = 1, NStn if (MyLat(XStn).NE.-999.0.AND.Lat(XStn).NE.-999.0.AND.abs(MyLat(XStn)-Lat(XStn)).LE.0.1) then if (MyLon(XStn).NE.-999.0.AND.Lon(XStn).NE.-999.0.AND.abs(MyLon(XStn)-Lon(XStn)).LE.0.1) then NameStn(XStn) = MyNameStn(XStn) ! NameLoc is already set to " nocode" end if end if NameCty(XStn) = MyNameCty(XStn) end do deallocate (MyLat,MyLon,MyElv,MyNameStn,MyNameCty,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: HarmoniseStn: Deallocation failure #####" Code = Code * 10 end subroutine HarmoniseStn !******************************************************************************* ! if pass 1, check values going into clim total at least 30 subroutine CheckClim do XVari = 1, 7 call SelectArraysClim ; call SelectArraysTot do XMonth = 1, NMonth do XStn = 1, NStn ! iterate by station do XHour = 1, NHour ! iterate by hour if (TotAny(XMonth,XHour,XStn).LT.ThreshClim) then ClimAny(XMonth,XHour,XStn) = -9999 ! sets missing else CountStnTot(XMonth,XHour,XVari)=CountStnTot(XMonth,XHour,XVari)+1 ! counts valid end if end do end do end do nullify (TotAny,ClimAny) end do end subroutine CheckClim !******************************************************************************* ! if pass 2, restore anomalies back to absolute values subroutine RestoreAbs do XVari = 1, 7 call SelectArraysClim ; call SelectArraysOut do XStn = 1, NStn ! iterate by station do XMonth = 1, NMonth ! iterate by month MonthClim=-9999 ; HourObs=0 ; Hour0=-9999 ; HourGap=-9999 ; Hour1=-9999 ; HourTot=0 do XHour = 1, NHour ! find which hours have clims if (ClimAny(XMonth,XHour,XStn).NE.-9999) then HourObs(XHour) = 1 HourTot = HourTot + 1 end if end do if (HourTot.EQ.8) then Hour0=1 ; HourGap=1 ; Hour1=8 else if (HourObs(1).EQ.1.AND.HourObs(3).EQ.1.AND.HourObs(5).EQ.1.AND.HourObs(7).EQ.1) then Hour0=1 ; HourGap=2 ; Hour1=7 else if (HourObs(2).EQ.1.AND.HourObs(4).EQ.1.AND.HourObs(6).EQ.1.AND.HourObs(8).EQ.1) then Hour0=2 ; HourGap=2 ; Hour1=8 else if (HourObs(1).EQ.1.AND.HourObs(5).EQ.1) then Hour0=1 ; HourGap=4 ; Hour1=5 else if (HourObs(2).EQ.1.AND.HourObs(6).EQ.1) then Hour0=2 ; HourGap=4 ; Hour1=6 else if (HourObs(3).EQ.1.AND.HourObs(7).EQ.1) then Hour0=3 ; HourGap=4 ; Hour1=7 else if (HourObs(4).EQ.1.AND.HourObs(8).EQ.1) then Hour0=4 ; HourGap=4 ; Hour1=8 end if if (Hour0.NE.-9999) then HourTot=0.0 ; HourEn=0.0 ! calc monthly clim do XHour = Hour0,Hour1,HourGap HourTot = HourTot + ClimAny(XMonth,XHour,XStn) HourEn = HourEn + 1.0 end do MonthClim = HourTot / HourEn do XYear = 1, NYear ! add clim back to anomalies if (OutAny(XYear,XMonth,XStn).NE.-9999) then OutAny(XYear,XMonth,XStn) = OutAny(XYear,XMonth,XStn) + MonthClim CountStnOut(XYear,XMonth,XVari)=CountStnOut(XYear,XMonth,XVari)+1 end if end do else do XYear = 1, NYear ! reject all data for this var/stn/cal-month OutAny(XYear,XMonth,XStn) = -9999 end do end if end do end do nullify (OutAny,ClimAny) end do end subroutine RestoreAbs !******************************************************************************* ! if pass 2, make wind direction from x,y components subroutine MakeDir do XStn = 1, NStn ! iterate by station do XYear = 1, NYear ! iterate by year do XMonth = 1, NMonth ! iterate by month if (OutWdx(XYear,XMonth,XStn).NE.-9999.AND.OutWdy(XYear,XMonth,XStn).NE.-9999) then Angle = atan(abs(OutWdx(XYear,XMonth,XStn)/OutWdy(XYear,XMonth,XStn))) Angle = Angle * 180.0 / Pi if (OutWdx(XYear,XMonth,XStn).GE.0.AND.OutWdy(XYear,XMonth,XStn).GE.0) then OutDir(XYear,XMonth,XStn) = Angle else if (OutWdx(XYear,XMonth,XStn).GE.0) then OutDir(XYear,XMonth,XStn) = 180.0 - Angle else if (OutWdy(XYear,XMonth,XStn).LT.0) then OutDir(XYear,XMonth,XStn) = 180.0 + Angle else OutDir(XYear,XMonth,XStn) = 360.0 - Angle end if CountStnOut(XYear,XMonth,8)=CountStnOut(XYear,XMonth,8)+1 end if end do end do end do end subroutine MakeDir !******************************************************************************* ! I know all the variales are named Save, but it reduces variable declarations! subroutine LoadSynClim SaveStem = "/tyn1/tim/data/obs/hahn/" do XVari = 1, 7 SaveTip = "clim" // OutSuffices(XVari) // ".txt" SaveFile = trim(SaveStem) // trim(SaveTip) print "(2a)", " > Loading from: ", trim(SaveTip) call SelectArraysClim open (2,file=SaveFile,status="old",access="sequential",form="formatted",action="read") do XStn = 1, NStn read (2,"(i8)"), TrashInt do XMonth = 1, NMonth read (2,"(8e13.5)"), (ClimAny(XMonth,XHour,XStn),XHour=1,NHour) end do end do close (2) nullify (ClimAny) end do end subroutine LoadSynClim !******************************************************************************* subroutine DumpSynClim SaveStem = "/tyn1/tim/data/hahn/" do XVari = 1, 7 SaveTip = "clim" // OutSuffices(XVari) // ".txt" SaveFile = trim(SaveStem) // trim(SaveTip) print "(2a)", " > Saving to: ", trim(SaveTip) call SelectArraysClim open (2,file=SaveFile,status="replace",access="sequential",form="formatted",action="write") do XStn = 1, NStn write (2,"(i8)"), Code(XStn) do XMonth = 1, NMonth write (2,"(8e13.5)"), (ClimAny(XMonth,XHour,XStn),XHour=1,NHour) end do end do close (2) nullify (ClimAny) end do end subroutine DumpSynClim !******************************************************************************* subroutine DumpCRUts allocate (SaveAny(NYear,NMonth,NStn), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DumpCRUts: Allocation failure: SaveAny #####" BegYearTxt = GetTextFromInt(BegYear) EndYearTxt = GetTextFromInt(EndYear) SaveStem = "/tyn1/tim/data/hahn/" do XVari = 1, 8 if (XVari.NE.6.AND.XVari.NE.7) then SaveTip = "hahn." // trim(BegYearTxt) // "-" // trim(EndYearTxt) // OutSuffices(XVari) // ".cts" SaveFile = trim(SaveStem) // trim(SaveTip) print "(2a)", " > Saving to: ", trim(SaveTip) call SelectArraysOut SaveAny = -9999 do XYear = 1, NYear do XMonth = 1, NMonth do XStn = 1, NStn if (OutAny(XYear,XMonth,XStn).NE.-9999) & SaveAny(XYear,XMonth,XStn)=nint(OutAny(XYear,XMonth,XStn)/OutMulti(XVari)) end do end do end do call MakeStnInfo (StnInfo,Code,Code,Lat,Lon,Elv,1,YearAD=YearAD,Data=SaveAny,Silent=1) call SaveCTS (StnInfo,NameLoc,NameStn,NameCty,SaveAny,YearAD,CallFile=SaveFile,Silent=1) deallocate (StnInfo, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DumpCRUts: Deallocation failure: StnInfo #####" nullify(OutAny) end if end do end subroutine DumpCRUts !******************************************************************************* subroutine DumpYrMonStats write (99,"(i4,a4,a)"), YearAD(XYear),MonthName(XMonth),": station totals" write (99,"(a)"), " DAY 00 03 06 09 12 15 18 21" do XDay = 1, MonthLengths(XYear,XMonth) write (99,"(i4,8i6)"), XDay,(CountStnIn(XDay,XHour),XHour=1,NHour) end do write (99,*) CountAllIn(XYear,XMonth) = sum(CountStnIn) end subroutine DumpYrMonStats !******************************************************************************* subroutine DumpOpStats write (99,"(a)"), "The inputs (hours*days*stations), and outputs (stations)." write (99,"(2a4,a8,8a6)"), "YEAR"," MON"," INPUTS",(OutSuffices(XVari),XVari=1,NVari) do XYear = 1, NYear do XMonth = 1, NMonth write (99,"(i4,a4,i8,8i6)"), YearAD(XYear),MonthName(XMonth),CountAllIn(XYear,XMonth), & (CountStnOut(XYear,XMonth,XVari),XVari=1,NVari) end do end do write (99,*) end subroutine DumpOpStats !******************************************************************************* subroutine DumpClimStats write (99,"(a)"), "The climatologies (stations)." write (99,"(2a4,8a6)"), " MON"," SYN",(OutSuffices(XVari),XVari=1,NVari) do XMonth = 1, NMonth do XHour = 1, NHour write (99,"(a4,i4,8i6)"), MonthName(XMonth),XHour,(CountStnTot(XMonth,XHour,XVari),XVari=1,NVari) end do end do write (99,*) end subroutine DumpClimStats !******************************************************************************* subroutine Conclude print* close (99) end subroutine Conclude !******************************************************************************* ! ['.oct','.slp','.wnd','.vap','.tmp','.wdx','.wdy','.dir'] subroutine SelectArraysIn if (XVari.EQ.1) then InAny => InOct else if (XVari.EQ.2) then InAny => InSLP else if (XVari.EQ.3) then InAny => InWnd else if (XVari.EQ.4) then InAny => InVap else if (XVari.EQ.5) then InAny => InTmp else if (XVari.EQ.6) then InAny => InWdx else if (XVari.EQ.7) then InAny => InWdy end if end subroutine SelectArraysIn !******************************************************************************* ! ['.oct','.slp','.wnd','.vap','.tmp','.wdx','.wdy','.dir'] subroutine SelectArraysClim if (XVari.EQ.1) then ClimAny => ClimOct else if (XVari.EQ.2) then ClimAny => ClimSLP else if (XVari.EQ.3) then ClimAny => ClimWnd else if (XVari.EQ.4) then ClimAny => ClimVap else if (XVari.EQ.5) then ClimAny => ClimTmp else if (XVari.EQ.6) then ClimAny => ClimWdx else if (XVari.EQ.7) then ClimAny => ClimWdy end if end subroutine SelectArraysClim !******************************************************************************* ! ['.oct','.slp','.wnd','.vap','.tmp','.wdx','.wdy','.dir'] subroutine SelectArraysTot if (XVari.EQ.1) then TotAny => TotOct else if (XVari.EQ.2) then TotAny => TotSLP else if (XVari.EQ.3) then TotAny => TotWnd else if (XVari.EQ.4) then TotAny => TotVap else if (XVari.EQ.5) then TotAny => TotTmp else if (XVari.EQ.6) then TotAny => TotWdx else if (XVari.EQ.7) then TotAny => TotWdy end if end subroutine SelectArraysTot !******************************************************************************* ! ['.oct','.slp','.wnd','.vap','.tmp','.wdx','.wdy','.dir'] subroutine SelectArraysOut if (XVari.EQ.1) then OutAny => OutOct else if (XVari.EQ.2) then OutAny => OutSLP else if (XVari.EQ.3) then OutAny => OutWnd else if (XVari.EQ.4) then OutAny => OutVap else if (XVari.EQ.5) then OutAny => OutTmp else if (XVari.EQ.6) then OutAny => OutWdx else if (XVari.EQ.7) then OutAny => OutWdy else if (XVari.EQ.8) then OutAny => OutDir end if end subroutine SelectArraysOut !******************************************************************************* end program GetHahn