! updatejl.f90 ! f90 program written by Tim Mitchell on 25.01.01 ! last modified on 25.01.01 ! tool to update standard .dat and .syn files from UKMO and text updates ! f90 -o ./../obs/updatejl filenames.f90 jldatfiles.f90 synfiles.f90 jlgeneral.f90 ./../obs/updatejl.f90 program UpdateJL use FileNames use JLDATFiles use SYNFiles use JLGeneral implicit none real, pointer, dimension (:,:,:,:) :: Flow, FileFlow real, pointer, dimension (:) :: LineReal integer, pointer, dimension (:,:,:) :: Lamb, FileLamb, Jenk, FileJenk, Auto, FileAuto, FileData integer, pointer, dimension (:,:) :: MonthLengths integer, pointer, dimension (:) :: YearAD, FileYearAD, LineInt real, parameter :: MissVal = -999.0 character (len=80), parameter :: Blank = "" real :: BlockMissVal, Multiplier real :: OpMiss, OpEn, OpFrac real :: LambMiss,JenkMiss,AutoMiss,FlowMiss,LambFrac,JenkFrac,AutoFrac,FlowFrac integer :: ReadStatus, AllocStat, MenuChoice integer :: StartYear, EndYear, FirstYear, YearN integer :: BlockYearN, BlockStartAD, BlockEndAD, BlockStartX, BlockEndX integer :: XYear, XMonth, XDay, XHeader, XFooter, XFileYear, XInt, XReal, XVari integer :: Year, Month, Day, Pos31, BegMon, EndMon integer :: HeaderN, FooterN, MonthN, DayN, VariN, StringLen, AbsentMonBegN, AbsentMonEndN integer :: FileYear0,FileYear1,Year0,Year1 integer :: QComp, QIntFloat, QFileComp character (len=80) :: GivenFile, OrigFile, LineFormat, Waste character (len=1) :: IntFloat !******************************************************************************* ! main 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.10) then call LoadFromSYN else if (MenuChoice.EQ.11) then QComp = 1 call LoadFromDAT else if (MenuChoice.EQ.12) then QComp = 2 call LoadFromDAT else if (MenuChoice.EQ.13) then QComp = 3 call LoadFromDAT else if (MenuChoice.EQ.14) then QComp = 4 call LoadOriginal else if (MenuChoice.EQ.15) then QComp = 5 call LoadOriginal else if (MenuChoice.EQ.20) then call SaveSYN (Blank,YearAD,Lamb,Jenk,Auto,Flow) print* else if (MenuChoice.EQ.21) then call SaveJLDAT (Blank,YearAD,Lamb) print* else if (MenuChoice.EQ.22) then call SaveJLDAT (Blank,YearAD,Jenk) print* else if (MenuChoice.EQ.23) then call SaveJLDAT (Blank,YearAD,Auto) print* else if (MenuChoice.EQ.30) then call CheckMaster else if (MenuChoice.NE.99) then print*, " > 1. Reinitialise" print*, " > 10. Load data from .syn" print*, " > 11. Load Lamb from .dat" print*, " > 12. Load Jenk from .dat" print*, " > 13. Load Auto from .dat" print*, " > 14. Load data from UKMO update" print*, " > 15. Load data from month per line file" print*, " > 20. Save data to .syn" print*, " > 21. Save Lamb to .dat" print*, " > 22. Save Jenk to .dat" print*, " > 23. Save Auto to .dat" print*, " > 30. Check main arrays" print*, " > 99. Exit" end if if (MenuChoice.EQ.99) exit end do call Conclude contains !******************************************************************************* ! intro subroutine Intro open (99,file="/cru/u2/f709762/data/scratch/log-ujl.dat",status="replace",action="write") print* print*, " > ##### UpdateJL.f90 ##### Tool for updating synoptic data #####" print* 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 YearN = EndYear - StartYear + 1 MonthN = 12 ; DayN = 31 ; VariN = 8 allocate ( Flow (YearN, MonthN, DayN, VariN), & Lamb (YearN, MonthN, DayN), & Jenk (YearN, MonthN, DayN), & Auto (YearN, MonthN, DayN), & YearAD (YearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: Intro: Allocation failure #####" Flow = MissVal Lamb = -9 ; Jenk = -9 ; Auto = -9 do XYear = 1, YearN YearAD (XYear) = StartYear + XYear - 1 end do print* end subroutine Intro !******************************************************************************* ! spec original subroutine LoadOriginal 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*, " > Enter the first year AD in the file: " do read (*,*,iostat=ReadStatus), FirstYear if (FirstYear.GT.YearAD(YearN)) then ReadStatus = 99 print*, " > Year beyond master array. Try again." end if if (ReadStatus.LE.0) exit end do BlockStartAD = FirstYear BlockStartX = FirstYear - StartYear + 1 open (2, file=OrigFile, status="old", access="sequential", form="formatted", action="read") 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(YearN)) 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 if (QComp.EQ.4) call LoadUKMO if (QComp.EQ.5) call LoadLineMon end if BlockStartAD = BlockEndAD + 1 BlockStartX = BlockEndX + 1 if (BlockStartAD.GT.YearAD(YearN)) then print*, " > End of block is also end of master array." BlockYearN = 0 end if if (BlockYearN.EQ.0) exit end do close (2) print* end subroutine LoadOriginal !******************************************************************************* ! load UKMO subroutine LoadUKMO print*, " > Final year in block = ", BlockEndAD BlockEndX = BlockEndAD - BlockStartAD + BlockStartX ! define BlockEndX print*, " > Enter the number of absent months at the start:" do read (*,*,iostat=ReadStatus), AbsentMonBegN if (ReadStatus.LE.0) exit end do print*, " > Enter the number of absent months at the end:" do read (*,*,iostat=ReadStatus), AbsentMonEndN if (ReadStatus.LE.0) exit end do print*, " > Enter the number of header lines per month:" do read (*,*,iostat=ReadStatus), HeaderN if (ReadStatus.LE.0) exit end do print*, " > Enter the number of footer lines per month:" do read (*,*,iostat=ReadStatus), FooterN if (ReadStatus.LE.0) exit end do print*, " > We assume one line of data per day (year,mon,day,Jenk,Auto,8*Flow)." print*, " > We assume that only existent days are included." print*, " > Enter the data line format, e.g. (i4,2i3,i4,i5,f9.1,4f7.1,3f8.1)" do read (*,*,iostat=ReadStatus), LineFormat StringLen = len (trim(LineFormat)) if (LineFormat(1:1).NE."(" .OR. LineFormat(StringLen:StringLen).NE.")") then ReadStatus = 99 print*, " > Format is unacceptable. Retry." end if if (ReadStatus.LE.0) exit end do allocate ( LineInt (2), & LineReal (VariN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: LoadUKMO: Allocation failure #####" call GetMonthLengths (YearAD,MonthLengths) do XYear = BlockStartX, BlockEndX BegMon = 1 ; EndMon = MonthN if (XYear.EQ.BlockStartX) BegMon = 1+AbsentMonBegN if (XYear.EQ.BlockEndX) EndMon = MonthN-AbsentMonEndN do XMonth = BegMon, EndMon if (HeaderN.GT.0) then ! read headers do XHeader = 1, HeaderN read (2, *), Waste end do end if do XDay = 1, MonthLengths(XYear,XMonth) ! read day read (2, LineFormat), Year, Month, Day, (LineInt(XInt),XInt=1,2), (LineReal(XReal),XReal=1,8) if (Year.GE.YearAD(1).AND.Year.LE.YearAD(YearN)) then Year = Year - YearAD(1) + 1 Jenk (Year,Month,Day) = LineInt(1) Auto (Year,Month,Day) = LineInt(2) do XReal = 1, 8 Flow (Year,XMonth,XDay,XReal) = LineReal(XReal) end do end if end do if (FooterN.GT.0) then ! read footers do XFooter = 1, FooterN read (2, *), Waste end do end if end do end do deallocate (LineInt,LineReal,MonthLengths, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: LoadUKMO: Deallocation failure #####" end subroutine LoadUKMO !******************************************************************************* ! load from raw data file with one month of data per line subroutine LoadLineMon 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 print*, " > Enter the number of absent months at the start:" do read (*,*,iostat=ReadStatus), AbsentMonBegN if (ReadStatus.LE.0) exit end do print*, " > Enter the number of absent months at the end:" do read (*,*,iostat=ReadStatus), AbsentMonEndN if (ReadStatus.LE.0) exit end do QIntFloat = 0 print*, " > We assume one line of data per month (31 days)." print*, " > Enter the data line format, e.g. (31i3 or 31f7.1)" do read (*,*,iostat=ReadStatus), LineFormat StringLen = len (trim(LineFormat)) Pos31 = index (LineFormat,'31') IntFloat = LineFormat ((Pos31+2):(Pos31+2)) if (LineFormat(1:1).NE."(" .OR. LineFormat(StringLen:StringLen).NE.")") then print*, " > Brackets are incorrect. Try again." else if (Pos31.EQ.0) then print*, " > '31' must be included in the format. Try again." else if (IntFloat.EQ.'I'.OR.IntFloat.EQ.'i') then print*, " > Data recognised as integers." QIntFloat = 1 else if (IntFloat.EQ.'F'.OR.IntFloat.EQ.'f') then print*, " > Data recognised as reals." QIntFloat = 2 else if (IntFloat.EQ.'E'.OR.IntFloat.EQ.'e') then print*, " > Data recognised as reals." QIntFloat = 2 else print*, " > Data format not recognised as integer or real. Try again." end if if (ReadStatus.LE.0) exit end do if (QIntFloat.EQ.1) then print*, " > Enter the variable: original LWT (=1), Jenk-Lamb LWT (=2), Jenk auto (=3): " do read (*,*,iostat=ReadStatus), QFileComp if (ReadStatus.LE.0.AND.QFileComp.GE.1.AND.QFileComp.LE.3) exit end do else if (QIntFloat.EQ.2) then print*, " > Enter the variable (1...8 = PM-1000,W,S,F,D,ZW,ZS,Z): " do read (*,*,iostat=ReadStatus), QFileComp if (ReadStatus.LE.0.AND.QFileComp.GE.1.AND.QFileComp.LE.8) exit end do end if do XYear = BlockStartX, BlockEndX if (HeaderN.GT.0) then ! read headers do XHeader = 1, HeaderN read (2, *), Waste end do end if BegMon = 1 ; EndMon = MonthN if (XYear.EQ.BlockStartX) BegMon = 1+AbsentMonBegN if (XYear.EQ.BlockEndX) EndMon = MonthN-AbsentMonEndN do XMonth = BegMon, EndMon ! read months if (QIntFloat.EQ.1) then if (QFileComp.EQ.1) read (2,LineFormat), (Lamb(XYear,XMonth,XDay), XDay=1,DayN) if (QFileComp.EQ.2) read (2,LineFormat), (Jenk(XYear,XMonth,XDay), XDay=1,DayN) if (QFileComp.EQ.3) read (2,LineFormat), (Auto(XYear,XMonth,XDay), XDay=1,DayN) else if (QIntFloat.EQ.2) then read (2,LineFormat), (Flow(XYear,XMonth,XDay,QFileComp), XDay=1,DayN) end if end do if (FooterN.GT.0) then ! read footers do XFooter = 1, FooterN read (2, *), Waste end do end if end do end subroutine LoadLineMon !******************************************************************************* ! load from .dat file subroutine LoadFromDAT call LoadJLDAT (Blank,FileYearAD,FileData) call CommonVecPer (FileYearAD,YearAD,FileYear0,FileYear1,Year0,Year1) 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 XYear = Year0 + XFileYear - FileYear0 do XMonth = 1, MonthN do XDay = 1, DayN if (QComp.EQ.1) Lamb(XYear,XMonth,XDay) = FileData(XFileYear,XMonth,XDay) if (QComp.EQ.2) Jenk(XYear,XMonth,XDay) = FileData(XFileYear,XMonth,XDay) if (QComp.EQ.3) Auto(XYear,XMonth,XDay) = FileData(XFileYear,XMonth,XDay) end do end do end do deallocate (FileYearAD, FileData, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: LoadFromDAT: Deallocation failure #####" print* end subroutine LoadFromDAT !******************************************************************************* ! load from .syn file subroutine LoadFromSYN call LoadSYN (Blank,FileYearAD,FileLamb,FileJenk,FileAuto,FileFlow) call CommonVecPer (FileYearAD,YearAD,FileYear0,FileYear1,Year0,Year1) 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 XYear = Year0 + XFileYear - FileYear0 do XMonth = 1, MonthN do XDay = 1, DayN Lamb(XYear,XMonth,XDay) = FileLamb(XFileYear,XMonth,XDay) Jenk(XYear,XMonth,XDay) = FileJenk(XFileYear,XMonth,XDay) Auto(XYear,XMonth,XDay) = FileAuto(XFileYear,XMonth,XDay) do XVari = 1, VariN Flow(XYear,XMonth,XDay,XVari) = FileFlow(XFileYear,XMonth,XDay,XVari) end do end do end do end do deallocate (FileYearAD,FileLamb,FileJenk,FileAuto,FileFlow, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: LoadFromSYN: Deallocation failure #####" print* end subroutine LoadFromSYN !******************************************************************************* ! check master array subroutine CheckMaster call GetMonthLengths (YearAD,MonthLengths) OpEn = 0.0 LambMiss = 0.0 ; JenkMiss = 0.0 ; AutoMiss = 0.0 ; FlowMiss = 0.0 do XYear = 1, YearN do XMonth = 1, MonthN do XDay = 1, MonthLengths(XYear,XMonth) OpEn = OpEn + 1.0 if (Lamb (XYear,XMonth,XDay) .EQ. -9) LambMiss = LambMiss + 1.0 if (Jenk (XYear,XMonth,XDay) .EQ. -9) JenkMiss = JenkMiss + 1.0 if (Auto (XYear,XMonth,XDay) .EQ. -9) AutoMiss = AutoMiss + 1.0 do XVari = 1, VariN if (Flow (XYear,XMonth,XDay,XVari) .EQ. MissVal) FlowMiss = FlowMiss + 1.0 end do end do end do end do LambFrac = 100.0 * LambMiss / OpEn JenkFrac = 100.0 * JenkMiss / OpEn AutoFrac = 100.0 * AutoMiss / OpEn FlowFrac = 100.0 * FlowMiss / (OpEn*VariN) print "(a38,f10.2)", " > Number of days in main array: ", OpEn print "(a40,4f8.2)", " > Missing % for Lamb,Jenk,Auto,Flow: ", LambFrac,JenkFrac,AutoFrac,FlowFrac print* deallocate (MonthLengths,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CheckMaster: Deallocation failure #####" end subroutine CheckMaster !******************************************************************************* ! conclude subroutine Conclude deallocate (YearAD,Lamb,Jenk,Auto,Flow,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: Conclude: Deallocation failure #####" close (99) print* end subroutine Conclude !******************************************************************************* end program UpdateJL