! makemonthlyeasy.f90 ! f90 program written by Tim Mitchell on 19.12.00 ! last modified on 04.01.02 ! tool to transform messy monthly data sets into clean ones with a single formatting structure ! pgf90 -Mstandard -Minfo -fast -Mscalarsse -Mvect=sse -Mflushz ! -o ./../obs/makemonthlyeasy filenames.f90 perfiles.f90 time.f90 ! ./../obs/makemonthlyeasy.f90 2> /tyn1/tim/scratch/stderr.txt program MakeMonthlyEasy use FileNames use PerFiles use Time ! use CETGeneral implicit none real, dimension (:,:), pointer :: MasterMonthly, FileMonthly real, dimension (:,:), pointer :: MasterSeasonal, FileSeasonal real, dimension (:), pointer :: MasterAnnual, FileAnnual real, dimension (12) :: LineReal integer, pointer, dimension (:,:) :: MonthLengths integer, pointer, dimension (:) :: YearAD, FileYearAD integer, dimension (12) :: LineInt, LineData integer, dimension (4) :: RawSeaCode real, parameter :: MissVal = -999.0 character (len=80), parameter :: Blank = "" real :: BlockMissVal, Multiplier integer :: ReadStatus, AllocStat integer :: MenuChoice integer :: StartYear, EndYear, FirstYear, MasterYearN,FileHeadN,XFileHead integer :: BlockYearN, BlockStartAD, BlockEndAD, BlockStartX, BlockEndX integer :: XYear, XMonth, XDay, XHeader, XFooter, XFileYear, XMasterYear, XSeason integer :: HeaderN, FooterN, StringLen, MastYear,MastSeas, ThisYear,ThisMonth integer :: FileYear0,FileYear1,MasterYear0,MasterYear1 integer :: VariCode,PosChar integer :: QIntReal,QLineYearMon,QMonSea,QFirstSea character (len=80) :: GivenFile, OrigFile, LineFormat, Waste character (len=1) :: CharIntReal !******************************************************************************* ! main open (99,file="/tyn1/tim/scratch/log-mme.dat",status="replace",action="write") print* print*, " > ##### MakeMonthlyEasy.f90 ##### Tool for reformatting #####" print* call Intro do print*, " > Main menu. Make your choice. (0=list)" do read (*,*,iostat=ReadStatus), MenuChoice if (ReadStatus.LE.0) exit end do if (MenuChoice.EQ.1) then print*, " > Are you sure? (1=no,2=yes)" do read (*,*,iostat=ReadStatus), MenuChoice if (ReadStatus.LE.0.AND.MenuChoice.GE.1.AND.MenuChoice.LE.2) exit end do if (MenuChoice.EQ.1) print*, " > No changes made." if (MenuChoice.EQ.2) call Intro else if (MenuChoice.EQ.2) then call SpecOriginal call LoadOriginal else if (MenuChoice.EQ.3) then call LoadFromPER else if (MenuChoice.EQ.4) then if (VariCode.LT.-1.OR.VariCode.GT.2) then print*, " > Enter the variable (-1=min,0=mean,1=max,2=sum): " do read (*,*,iostat=ReadStatus), VariCode if (ReadStatus.LE.0.AND.VariCode.GE.-1.AND.VariCode.LE.2) exit end do end if call SavePER (Blank,YearAD,VariCode,Monthly=MasterMonthly,Seasonal=MasterSeasonal,Annual=MasterAnnual) print* else if (MenuChoice.EQ.5) then if (VariCode.LT.-1.OR.VariCode.GT.2) then print*, " > Enter the variable (-1=min,0=mean,1=max,2=sum): " do read (*,*,iostat=ReadStatus), VariCode if (ReadStatus.LE.0.AND.VariCode.GE.-1.AND.VariCode.LE.2) exit end do end if call SaveCETMON (Blank,VariCode,YearAD,MasterMonthly,MasterSeasonal,MasterAnnual) print* else if (MenuChoice.EQ.6) then call DeriveSeaMon else if (MenuChoice.EQ.7) then call DeriveAnnMon else if (MenuChoice.EQ.8) then call DeriveAnnSea else if (MenuChoice.NE.99) then print*, " > 1. Reinitialise" print*, " > 2. Load data from raw file" print*, " > 3. Load data from .per file" print*, " > 4. Save to .per file" print*, " > 5. Save to .mon file" print*, " > 6. Derive seasonal from monthly data" print*, " > 7. Derive annual from monthly data" print*, " > 8. Derive annual from seasonal data" print*, " > 99. Exit" end if if (MenuChoice.EQ.99) exit end do call Conclude contains !******************************************************************************* ! intro subroutine Intro print*, " > Enter the start and end years AD of the master array:" do read (*,*,iostat=ReadStatus), StartYear, EndYear if (ReadStatus.LE.0 .AND. StartYear.LE.EndYear) exit end do MasterYearN = EndYear - StartYear + 1 allocate ( MasterMonthly (MasterYearN, 12), & MasterSeasonal(MasterYearN, 4), & MasterAnnual (MasterYearN), & YearAD (MasterYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: Intro: Allocation failure #####" print*, MasterYearN,size(MasterMonthly,1),size(MasterMonthly,2) MasterMonthly = MissVal MasterSeasonal = MissVal MasterAnnual = MissVal do XYear = 1, MasterYearN YearAD (XYear) = StartYear + XYear - 1 end do VariCode = MissVal print* end subroutine Intro !******************************************************************************* ! spec original subroutine SpecOriginal print*, " > Enter the original file path/name:" do do read (*,*,iostat=ReadStatus), GivenFile if (ReadStatus.LE.0) exit end do inquire (file=GivenFile, name=OrigFile) open (1, file=OrigFile, status="old", access="sequential", form="formatted", & action="read", iostat=ReadStatus) if (ReadStatus .NE. 0) print*, " > Cannot open file. Try again." if (ReadStatus .EQ. 0) close (1) if (ReadStatus .EQ. 0) exit end do print*, " > Identify the content: months (=1) or seasons (=2) ?" do read (*,*,iostat=ReadStatus), QMonSea if (ReadStatus.LE.0.AND.QMonSea.GE.1.AND.QMonSea.LE.2) exit end do if (QMonSea.EQ.1) then print*, " > Identify the structure: one line per year (=1) or month (=2) ?" do read (*,*,iostat=ReadStatus), QLineYearMon if (ReadStatus.LE.0.AND.QLineYearMon.GE.1.AND.QLineYearMon.LE.2) exit end do if (QLineYearMon.EQ.2) print*, " > The start=Jan & end=Dec: raw files may need padding." else if (QMonSea.EQ.2) then print*, " > Identify the structure: one line per year (=1) or season (=2) ?" do read (*,*,iostat=ReadStatus), QLineYearMon if (ReadStatus.LE.0.AND.QLineYearMon.GE.1.AND.QLineYearMon.LE.2) exit end do print*, " > Is the raw file MAM,JJA,SON,DJF (=1) or DJF,MAM,JJA,SON (=2) ?" do read (*,*,iostat=ReadStatus), QFirstSea if (ReadStatus.LE.0.AND.QFirstSea.GE.1.AND.QFirstSea.LE.2) exit end do if (QFirstSea.EQ.1) RawSeaCode = (/1,2,3,4/) if (QFirstSea.EQ.2) RawSeaCode = (/0,1,2,3/) if (QLineYearMon.EQ.2.AND.QFirstSea.EQ.1) print*, " > The start=MAM & end=DJF: raw files may need padding." if (QLineYearMon.EQ.2.AND.QFirstSea.EQ.2) print*, " > The start=DJF & end=SON: raw files may need padding." end if print*, " > Enter the no. file headers: " do read (*,*,iostat=ReadStatus), FileHeadN if (ReadStatus.LE.0.AND.FileHeadN.GE.0) exit end do print*, " > Enter the first year AD in the raw file: " do read (*,*,iostat=ReadStatus), FirstYear if (FirstYear.GT.YearAD(MasterYearN)) then ReadStatus = 99 print*, " > Year beyond master array. Try again." end if if (ReadStatus.LE.0) exit end do end subroutine SpecOriginal !******************************************************************************* ! load original subroutine LoadOriginal BlockStartAD = FirstYear BlockStartX = FirstYear - StartYear + 1 open (2, file=OrigFile, status="old", access="sequential", form="formatted", action="read") if (FileHeadN.GT.0) then do XfileHead=1,FileHeadN read (2, *), Waste end do end if do print* print*, " > New block. First year in block = ", BlockStartAD if (BlockStartAD.LT.YearAD(1)) then ! define BlockYearN, BlockEndAD BlockYearN = YearAD(1) - BlockStartAD BlockEndAD = BlockStartAD + BlockYearN - 1 print*, " > Block predates master array. Block length = ", BlockYearN else print*, " > Enter the number of years in the block (0=end):" do read (*,*,iostat=ReadStatus), BlockYearN BlockEndAD = BlockStartAD + BlockYearN - 1 if (BlockEndAD.GT.YearAD(MasterYearN)) then ReadStatus = 99 print*, " > Block extends beyond master array. Try again." end if if (ReadStatus.LE.0) exit end do end if if (BlockYearN.NE.0) then print*, " > Final year in block = ", BlockEndAD BlockEndX = BlockEndAD - BlockStartAD + BlockStartX ! define BlockEndX print*, " > Enter the number of header lines per year:" do read (*,*,iostat=ReadStatus), HeaderN if (ReadStatus.LE.0) exit end do print*, " > Enter the number of footer lines per year:" do read (*,*,iostat=ReadStatus), FooterN if (ReadStatus.LE.0) exit end do if (QMonSea.EQ.1) then if (QLineYearMon.EQ.1) print*, " > Enter the data line format, e.g. (a10,12i5) or (a4,12f8.1)" if (QLineYearMon.EQ.2) print*, " > Enter the data line format, e.g. (a10,1i5) or (a4,1f8.1)" else if (QMonSea.EQ.2) then if (QLineYearMon.EQ.1) print*, " > Enter the data line format, e.g. (a10,4i5) or (a4,4f8.1)" if (QLineYearMon.EQ.2) print*, " > Enter the data line format, e.g. (a10,1i5) or (a4,1f8.1)" end if do read (*,*,iostat=ReadStatus), LineFormat StringLen = len (trim(LineFormat)) PosChar = max (scan(LineFormat,'I'),scan(LineFormat,'i'),scan(LineFormat,'F'),scan(LineFormat,'f')) PosChar = max (scan(LineFormat,'E'),scan(LineFormat,'e'),PosChar) CharIntReal = "" if (PosChar.GT.0) CharIntReal = LineFormat(PosChar:PosChar) if (LineFormat(1:1).NE."(" .OR. LineFormat(StringLen:StringLen).NE.")") then ReadStatus = 99 print*, " > Format is unacceptable. Retry." else if (CharIntReal.EQ.'I'.OR.CharIntReal.EQ.'i') then QIntReal = 1 else if (CharIntReal.EQ.'F'.OR.CharIntReal.EQ.'f') then QIntReal = 2 else if (CharIntReal.EQ.'E'.OR.CharIntReal.EQ.'e') then QIntReal = 2 else ReadStatus = 99 print*, " > Format is unacceptable. Retry." end if end if if (ReadStatus.LE.0) exit end do print*, " > Enter the missing value: " do read (*,*,iostat=ReadStatus), BlockMissVal if (ReadStatus.LE.0) exit end do print*, " > Enter the multiplier: " do read (*,*,iostat=ReadStatus), Multiplier if (ReadStatus.LE.0) exit end do print*, size(MasterMonthly) ! ################### do XYear = BlockStartX, BlockEndX ! print*, XYear ! ###################### if (HeaderN.GT.0) then ! read headers do XHeader = 1, HeaderN read (2, *), Waste end do end if if (QMonSea.EQ.1) then if (QLineYearMon.EQ.1) then if (QIntReal.EQ.1) read (2, LineFormat), Waste, (LineInt (XMonth), XMonth=1,12) if (QIntReal.EQ.2) read (2, LineFormat), Waste, (LineReal (XMonth), XMonth=1,12) else if (QLineYearMon.EQ.2) then do XMonth = 1, 12 if (QIntReal.EQ.1) read (2, LineFormat), Waste, LineInt (XMonth) if (QIntReal.EQ.2) read (2, LineFormat), Waste, LineReal (XMonth) end do end if else if (QMonSea.EQ.2) then if (QLineYearMon.EQ.1) then if (QIntReal.EQ.1) read (2, LineFormat), Waste, (LineInt (XSeason), XSeason=1,4) if (QIntReal.EQ.2) read (2, LineFormat), Waste, (LineReal (XSeason), XSeason=1,4) else if (QLineYearMon.EQ.2) then do XSeason = 1, 4 if (QIntReal.EQ.1) read (2, LineFormat), Waste, LineInt (XSeason) if (QIntReal.EQ.2) read (2, LineFormat), Waste, LineReal (XSeason) end do end if end if if (BlockStartX.GE.1) then if (QMonSea.EQ.1) then do XMonth = 1, 12 if (LineInt(XMonth).NE.BlockMissVal.AND.LineReal(XMonth).NE.BlockMissVal) then if (QIntReal.EQ.1) MasterMonthly (XYear,XMonth) = real (LineInt(XMonth)) if (QIntReal.EQ.2) MasterMonthly (XYear,XMonth) = LineReal(XMonth) MasterMonthly (XYear,XMonth) = MasterMonthly (XYear,XMonth) * Multiplier else MasterMonthly (XYear,XMonth) = MissVal end if end do else if (QMonSea.EQ.2) then do XSeason = 1, 4 if (RawSeaCode(XSeason).GE.1) then MastYear = XYear ; MastSeas = RawSeaCode(XSeason) else MastYear = XYear-1 ; MastSeas = 4 end if if (MastYear.GE.1) then if (LineInt(XSeason).NE.BlockMissVal.AND.LineReal(XSeason).NE.BlockMissVal) then if (QIntReal.EQ.1) MasterSeasonal (MastYear,MastSeas) = real (LineInt(XSeason)) if (QIntReal.EQ.2) MasterSeasonal (MastYear,MastSeas) = LineReal(XSeason) MasterSeasonal (MastYear,MastSeas) = MasterSeasonal (MastYear,MastSeas) * Multiplier else MasterSeasonal (MastYear,MastSeas) = MissVal end if else print*, " > ***** data error: first data DJF outside master range *****" end if end do end if end if LineInt = 0 LineReal = 0 if (FooterN.GT.0) then ! read footers do XFooter = 1, FooterN read (2, *), Waste end do end if end do BlockStartAD = BlockEndAD + 1 BlockStartX = BlockEndX + 1 if (BlockStartAD.GT.YearAD(MasterYearN)) then print*, " > End of block is also end of master array." BlockYearN = 0 end if end if if (BlockYearN.EQ.0) exit end do close (2) print* end subroutine LoadOriginal !******************************************************************************* ! load from .day file subroutine LoadFromPER call LoadPER (Blank,VariCode,FileYearAD,FileMonthly,FileSeasonal,FileAnnual) call CommonVecPer (FileYearAD,YearAD,FileYear0,FileYear1,MasterYear0,MasterYear1) if (FileYear0.EQ.MissVal) then print*, " > The loaded file has no period in common with the master array." else print*, " > Common period loaded into master array: ", FileYearAD(FileYear0), FileYearAD(FileYear1) end if do XFileYear = FileYear0, FileYear1 XMasterYear = MasterYear0 + XFileYear - FileYear0 do XMonth = 1, 12 MasterMonthly(XMasterYear,XMonth) = FileMonthly(XFileYear,XMonth) end do do XSeason = 1, 4 MasterSeasonal(XMasterYear,XSeason) = FileSeasonal(XFileYear,XSeason) end do MasterAnnual(XMasterYear) = FileAnnual(XFileYear) end do deallocate (FileYearAD,FileMonthly,FileSeasonal,FileAnnual, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: LoadFromDAY: Deallocation failure #####" print* end subroutine LoadFromPER !******************************************************************************* ! derive seasonal and annual data subroutine DeriveSeaMon if (VariCode.LT.-1.OR.VariCode.GT.2) then print*, " > Enter the monthly variable (-1=min,0=mean,1=max,2=sum):" do read (*,*,iostat=ReadStatus), VariCode if (ReadStatus.LE.0.AND.VariCode.GE.-1.AND.VariCode.LE.2) exit end do end if allocate (FileAnnual (MasterYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DeriveSeaMon: Allocation failure #####" FileAnnual = MissVal ! if (VariCode.EQ.-1) call FillSeaAnnMin (YearAD,MasterMonthly,MasterSeasonal,FileAnnual) ! if (VariCode.EQ. 0) call FillSeaAnnMean (YearAD,MasterMonthly,MasterSeasonal,FileAnnual) ! if (VariCode.EQ. 1) call FillSeaAnnMax (YearAD,MasterMonthly,MasterSeasonal,FileAnnual) ! if (VariCode.EQ. 2) call FillSeaAnnSum (YearAD,MasterMonthly,MasterSeasonal,FileAnnual) deallocate (FileAnnual,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DeriveSeaMon: Deallocation failure #####" print* end subroutine DeriveSeaMon !******************************************************************************* ! derive seasonal and annual data subroutine DeriveAnnMon if (VariCode.LT.-1.OR.VariCode.GT.2) then print*, " > Enter the monthly variable (-1=min,0=mean,1=max,2=sum):" do read (*,*,iostat=ReadStatus), VariCode if (ReadStatus.LE.0.AND.VariCode.GE.-1.AND.VariCode.LE.2) exit end do end if allocate (FileSeasonal (MasterYearN, 4), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DeriveAnnMon: Allocation failure #####" FileSeasonal = MissVal ! if (VariCode.EQ.-1) call FillSeaAnnMin (YearAD,MasterMonthly,FileSeasonal,MasterAnnual) ! if (VariCode.EQ. 0) call FillSeaAnnMean (YearAD,MasterMonthly,FileSeasonal,MasterAnnual) ! if (VariCode.EQ. 1) call FillSeaAnnMax (YearAD,MasterMonthly,FileSeasonal,MasterAnnual) ! if (VariCode.EQ. 2) call FillSeaAnnSum (YearAD,MasterMonthly,FileSeasonal,MasterAnnual) deallocate (FileSeasonal,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DeriveAnnMon: Deallocation failure #####" print* end subroutine DeriveAnnMon !******************************************************************************* ! derive seasonal and annual data subroutine DeriveAnnSea if (VariCode.LT.-1.OR.VariCode.GT.2) then print*, " > Enter the seasonal variable (-1=min,0=mean,1=max,2=sum):" do read (*,*,iostat=ReadStatus), VariCode if (ReadStatus.LE.0.AND.VariCode.GE.-1.AND.VariCode.LE.2) exit end do end if allocate (FileMonthly (MasterYearN,12), & FileSeasonal (MasterYearN, 4), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DeriveAnnSea: Allocation failure #####" FileMonthly = MissVal ; FileSeasonal = MissVal do XYear = 1, MasterYearN do XSeason = 1, 4 do XMonth = 1, 3 ThisMonth = 2 + ((XSeason-1)*3) + XMonth ThisYear = XYear if (ThisMonth.GT.12) then ThisYear = ThisYear + 1 ; ThisMonth = ThisMonth - 12 end if if (ThisYear.LE.MasterYearN) then FileMonthly (ThisYear,ThisMonth) = MasterSeasonal (XYear,XSeason) end if end do end do end do ! if (VariCode.EQ.-1) call FillSeaAnnMin (YearAD,FileMonthly,FileSeasonal,MasterAnnual) ! if (VariCode.EQ. 0) call FillSeaAnnMean (YearAD,FileMonthly,FileSeasonal,MasterAnnual) ! if (VariCode.EQ. 1) call FillSeaAnnMax (YearAD,FileMonthly,FileSeasonal,MasterAnnual) ! if (VariCode.EQ. 2) call FillSeaAnnSum (YearAD,FileMonthly,FileSeasonal,MasterAnnual) deallocate (FileMonthly,FileSeasonal,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DeriveAnnSea: Deallocation failure #####" print* end subroutine DeriveAnnSea !******************************************************************************* ! conclude subroutine Conclude deallocate (MasterMonthly,MasterSeasonal,MasterAnnual,YearAD,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: Conclude: Deallocation failure #####" close (99) print* end subroutine Conclude !******************************************************************************* end program MakeMonthlyEasy