! opann.f90 ! f90 program written by Tim Mitchell on 29.01.01 ! last modified on 21.11.01 ! tool to operate on standard .ann files ! pgf90 -Mstandard -Minfo -fast -Mscalarsse -Mvect=sse -Mflushz ! -o ./../obs/opann filenames.f90 annfiles.f90 sortmod.f90 usesort.f90 ! basicfun.f90 time.f90 plainperm.f90 regress.f90 pattscale.f90 ! ./../obs/opann.f90 2> /tyn1/tim/scratch/stderr.txt program OpAnn use FileNames use AnnFiles use SortMod use UseSort use BasicFun use Time use PlainPerm use Regress use PattScale implicit none real, pointer, dimension (:,:) :: Data, FileData real, pointer, dimension (:) :: OpVec, ResultVecA, ResultVecB, LSRExe, LSRWye integer, pointer, dimension (:) :: YearAD, FileYearAD character (len=80), pointer, dimension (:) :: FileBatch character (len= 9), pointer, dimension (:) :: ColTitles, FileColTitles real, parameter :: MissVal = -999.0 character (len=80), parameter :: Blank = "" real :: RealConstant, Speed, Force, MissAccept real :: DataMiss, DataMean, DataTot, DataFrac, OpMiss,OpEn,OpFrac,OpTot,OpBase,OpThresh,OpMean real :: Forc2co2,FitAlpha,FitBeta,Sens2co2Init,DTDt,Forc,EffClimSens,LastEffClimSens real :: Trash1,Trash2, KayX,KayY integer :: ReadStatus, AllocStat, MenuChoice, NextFree integer :: ChosenCol, ChosenColA, ChosenColB, ChosenColF, ChosenColZ, ChosenOp integer :: StartYear, EndYear, FirstYear, YearN, FileN integer :: BlockYearN, BlockStartAD, BlockEndAD, BlockStartX, BlockEndX, XFile integer :: XYear, XFileYear, XCol, XFileCol, XLoadCol, XSaveCol, XTrendYear integer :: StringLen, ColN, LoadColN, FileColN, SaveColN integer :: FileYear0,FileYear1,Year0,Year1,Day0,Day1,Month0,Month1,Julian0,Julian1,TrendYear0,TrendYear1 integer :: QComp, QIntFloat, QFileComp, QKeepMiss, QAbsRel integer :: NonBlank, IntConstant, Overlap, THalf, PerLen, GapLen,TrendTLen integer :: BaseYear0,BaseYear1, BaseADYear0,BaseADYear1, BaseYearN 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. 2) then call OperateAk else if (MenuChoice.EQ. 3) then call OperateAB else if (MenuChoice.EQ. 4) then call GaussSmoothA else if (MenuChoice.EQ. 5) then call AnomaliseA else if (MenuChoice.EQ. 6) then call CombineAB else if (MenuChoice.EQ. 7) then call MaskAB else if (MenuChoice.EQ.10) then call LoadFromANN else if (MenuChoice.EQ.11) then call LoadFromANNset else if (MenuChoice.EQ.20) then call DumpToANN else if (MenuChoice.EQ.30) then call CheckMaster else if (MenuChoice.EQ.40) then call CalcEquT else if (MenuChoice.EQ.41) then call PrintPeriodMean else if (MenuChoice.NE.99) then print*, " > 1. Reinitialise" print*, " > 2. Operate A.k" print*, " > 3. Operate A.B" print*, " > 4. Smooth A with Gaussian filter" print*, " > 5. Anomalise A relative to period" print*, " > 6. Combine columns A and B" print*, " > 7. Where A=x B=y" print*, " > 10. Load data from .ann" print*, " > 11. Load data from set of .ann files" print*, " > 20. Save data to .ann" print*, " > 30. Check main arrays" print*, " > 40. Calc equilib T: A(gloT),B(forc)" print*, " > 41. Print period mean" print*, " > 99. Exit" end if if (MenuChoice.EQ.99) exit end do call Conclude contains !******************************************************************************* ! intro subroutine Intro open (99,file="./../../../scratch/log-opann.dat",status="replace",action="write") print* print*, " > ##### OpAnn.f90 ##### Tool for operating on .ann files #####" print* MissAccept = 10.0 print*, " > Enter the number of columns in the master array:" do read (*,*,iostat=ReadStatus), ColN if (ReadStatus.LE.0 .AND. ColN.GE.1) exit end do 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 NextFree = 1 allocate ( Data (YearN, ColN), & ColTitles (ColN), & YearAD (YearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: Intro: Allocation failure #####" Data = MissVal ColTitles = 'X' do XYear = 1, YearN YearAD (XYear) = StartYear + XYear - 1 end do print* end subroutine Intro !******************************************************************************* ! load from .ann file subroutine LoadFromANN call LoadANN (Blank, FileYearAD, FileColTitles, 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*, " > The common period is: ", FileYearAD(FileYear0), FileYearAD(FileYear1) end if FileColN = size (FileColTitles) print*, " > COL TITLE" do XCol = 1, FileColN print "(i8,a9)", XCol, FileColTitles(XCol) end do if (FileColN.GT.1) then print*, " > Enter the number of columns to include in array: " do read (*,*,iostat=ReadStatus), LoadColN if (ReadStatus.LE.0 .AND. LoadColN.GE.1 .AND. LoadColN.LE.FileColN) exit end do else LoadColN = 1 end if do XLoadCol = 1, LoadColN if (LoadColN.LT.FileColN) then print "(a47,i4)", " > Select column from file --> array column: ", NextFree do read (*,*,iostat=ReadStatus), ChosenCol if (ReadStatus.LE.0 .AND. ChosenCol.GE.1 .AND. ChosenCol.LE.FileColN) exit end do else ChosenCol = XLoadCol end if ColTitles(NextFree) = FileColTitles(ChosenCol) do XFileYear = FileYear0, FileYear1 XYear = Year0 + XFileYear - FileYear0 Data(XYear,NextFree) = FileData(XFileYear,ChosenCol) end do call StoreMoveOn end do deallocate (FileYearAD,FileColTitles,FileData, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: LoadFromANN: Deallocation failure #####" print* end subroutine LoadFromANN !******************************************************************************* ! load from set of .ann files subroutine LoadFromANNset GivenFile = "" call GetBatch (GivenFile,FileBatch) FileN = size(FileBatch) do XFile = 1, FileN call LoadANN (FileBatch(XFile), FileYearAD, FileColTitles, FileData) call CommonVecPer (FileYearAD,YearAD,FileYear0,FileYear1,Year0,Year1) LoadColN = size (FileColTitles) do XLoadCol = 1, LoadColN do XFileYear = FileYear0, FileYear1 XYear = Year0 + XFileYear - FileYear0 Data(XYear,NextFree) = FileData(XFileYear,XLoadCol) end do ColTitles(NextFree) = FileColTitles(XLoadCol) call StoreMoveOn end do deallocate (FileYearAD,FileColTitles,FileData, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: LoadFromANN: Deallocation failure #####" end do end subroutine LoadFromANNset !******************************************************************************* ! smooth a column with a Gaussian filter subroutine GaussSmoothA call SelectColumn print*, " > Select the periodicity at which to smooth: " do read (*,*,iostat=ReadStatus), THalf if (ReadStatus.LE.0 .AND. THalf.GE.1 .AND. THalf.LE.YearN) exit end do print*, " > Replace (=1) or retain (=2) missing values ?" do read (*,*,iostat=ReadStatus), QKeepMiss if (ReadStatus.LE.0 .AND. QKeepMiss.GE.1 .AND. QKeepMiss.LE.2) exit end do allocate (OpVec (YearN), & ResultVecA (YearN), & ResultVecB (YearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GaussSmoothA: Allocation failure #####" OpVec = MissVal do XYear = 1, YearN OpVec (XYear) = Data (XYear,ChosenCol) end do call GaussSmooth (YearN,THalf,QKeepMiss,OpVec,ResultVecA,ResultVecB) do XYear = 1, YearN Data (XYear,NextFree) = ResultVecA (XYear) end do deallocate (OpVec,ResultVecA,ResultVecB, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GaussSmoothA: Deallocation failure #####" call StoreMoveOn print* end subroutine GaussSmoothA !******************************************************************************* ! anomalise a period against a column within it subroutine AnomaliseA call SelectColumn print*, " > Select first, last years AD as base period: " do read (*,*,iostat=ReadStatus), BaseADYear0,BaseADYear1 if (ReadStatus.LE.0.AND.BaseADYear0.GE.YearAD(1).AND.BaseADYear1.LE.YearAD(YearN) & .AND.BaseADYear1.GE.BaseADYear0) exit end do print*, " > Use absolute (=0, minus) or relative (=1, divide) anomalies? " do read (*,*,iostat=ReadStatus), QAbsRel if (ReadStatus.LE.0.AND.QAbsRel.GE.0.AND.QAbsRel.LE.1) exit end do BaseYearN = BaseADYear1 - BaseADYear0 + 1 BaseYear0 = BaseADYear0 - YearAD(1) + 1 BaseYear1 = BaseYear0 + BaseYearN - 1 OpThresh = real(BaseYearN) * (MissAccept / 100.0) OpTot = 0.0 OpMiss = 0.0 do XYear = BaseYear0, BaseYear1 if (Data (XYear,ChosenCol) .NE. MissVal) then OpTot = OpTot + Data (XYear,ChosenCol) else OpMiss = OpMiss + 1 end if end do if (OpMiss.GT.OpThresh) then print*, " > Too many missing values in base period to calc anomalies." else OpBase = OpTot / (real(BaseYearN) - OpMiss) end if do XYear = 1, YearN if (Data (XYear,ChosenCol).NE.MissVal) then if (QAbsRel.EQ.0) then Data (XYear,NextFree) = Data (XYear,ChosenCol) - OpBase else if (OpBase.NE.0) Data (XYear,NextFree) = Data (XYear,ChosenCol) / OpBase end if else Data (XYear,NextFree) = MissVal end if end do call StoreMoveOn print* end subroutine AnomaliseA !******************************************************************************* ! mask A . B subroutine MaskAB print*, " > Select columns A and B in turn: " call SelectColumn ChosenColA = ChosenCol call SelectColumn ChosenColB = ChosenCol print*, " > Select x and y:" do read (*,*,iostat=ReadStatus), KayX,KayY if (ReadStatus.LE.0) exit end do do XYear = 1, YearN Data(XYear,NextFree) = Data(XYear,ChosenColB) if (Data(XYear,ChosenColA).EQ.KayX) Data(XYear,NextFree) = KayY end do call StoreMoveOn print* end subroutine MaskAB !******************************************************************************* ! combine A . B subroutine CombineAB print*, " > Select columns A and B in turn: " call SelectColumn ChosenColA = ChosenCol call SelectColumn ChosenColB = ChosenCol do XYear = 1, YearN if (Data(XYear,ChosenColA).NE.MissVal.AND.Data(XYear,ChosenColB).EQ.MissVal) then Data(XYear,NextFree) = Data(XYear,ChosenColA) else if (Data(XYear,ChosenColA).EQ.MissVal.AND.Data(XYear,ChosenColB).NE.MissVal) then Data(XYear,NextFree) = Data(XYear,ChosenColB) else Data(XYear,NextFree) = MissVal end if end do call StoreMoveOn print* end subroutine CombineAB !******************************************************************************* ! operate A . constant subroutine OperateAk print*, " > Select the operation: A/k=1, A*k=2, A-k=3, A+k=4, sqrt(A)=5, A**k=6," print*, " > abs(A)=7, log(A)=8, e(A)=9, ln(A)=10:" do read (*,*,iostat=ReadStatus), ChosenOp if (ReadStatus.LE.0 .AND. ChosenOp.GE.1 .AND. ChosenOp.LE.10) exit end do call SelectColumn if (ChosenOp.LT.7.AND.ChosenOp.NE.5) then print*, " > Select the real constant: " do read (*,*,iostat=ReadStatus), RealConstant if (ReadStatus.LE.0) exit end do end if do XYear = 1, YearN Data(XYear,NextFree) = OpAwithB (Data(XYear,ChosenCol),RealConstant,ChosenOp) end do call StoreMoveOn print* end subroutine OperateAk !******************************************************************************* ! operate A . B subroutine OperateAB print*, " > Select the operation (A/B=1, A*B=2, A-B=3, A+B=4, A**B=6: " do read (*,*,iostat=ReadStatus), ChosenOp if (ReadStatus.LE.0 .AND. ChosenOp.GE.1 .AND. ChosenOp.LE.6 .AND. ChosenOp.NE.5) exit end do print*, " > Select columns A and B in turn: " call SelectColumn ChosenColA = ChosenCol call SelectColumn ChosenColB = ChosenCol do XYear = 1, YearN Data(XYear,NextFree) = OpAwithB (Data(XYear,ChosenColA),Data(XYear,ChosenColB),ChosenOp) end do call StoreMoveOn print* end subroutine OperateAB !******************************************************************************* ! check master array subroutine CheckMaster print "(a25)", " > COL MISS% MEAN" do XCol = 1, ColN DataMiss = 0.0 ; DataTot = 0.0 ; DataMean = MissVal do XYear = 1, YearN if (Data (XYear,XCol) .EQ. MissVal) then DataMiss = DataMiss + 1.0 else DataTot = DataTot + Data (XYear,XCol) end if end do DataFrac = 100.0 * DataMiss / YearN if ((YearN-DataMiss).GT.0) DataMean = DataTot / (YearN-DataMiss) print "(i9,f8.2,f8.2,a1,a9)", XCol, DataFrac, DataMean, " ", ColTitles(XCol) end do print* end subroutine CheckMaster !******************************************************************************* ! calc equilibrium temperature subroutine CalcEquT print*, " > Select cols A (global T anom.) and B (rad.forc.anom.) in turn: " call SelectColumn ChosenColA = ChosenCol call SelectColumn ChosenColB = ChosenCol call GetKaySet (0,Forc2co2,FitAlpha,FitBeta,Sens2co2Init,TrendTLen) print*, " > Select the period length: " do read (*,*,iostat=ReadStatus), PerLen if (ReadStatus.LE.0 .AND. PerLen.GE.1) exit end do allocate (LSRExe (TrendTLen), & LSRWye (TrendTLen), & OpVec (YearN), & ResultVecA(YearN), & ResultVecB(YearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcEquT: Allocation failure #####" do XYear = 1, YearN ! calculates Forc OpVec(XYear) = Data(XYear,ChosenColB) end do call GaussSmooth (YearN,PerLen,1,OpVec,ResultVecA,ResultVecB) LastEffClimSens = Sens2co2Init do XYear = 1, YearN TrendYear0 = nint (real(XYear)-(real(TrendTLen)/2.0)) TrendYear1 = TrendYear0 + TrendTLen - 1 LSRExe=MissVal ; LSRWye=MissVal do XTrendYear = TrendYear0, TrendYear1 ! calculates DTDt if (XTrendYear.GE.1.AND.XTrendYear.LE.YearN) then LSRExe (XTrendYear-TrendYear0+1) = XTrendYear-TrendYear0+1 LSRWye (XTrendYear-TrendYear0+1) = Data(XTrendYear,ChosenColA) end if end do call LinearLSRVec (LSRExe,LSRWye,Trash1,DTDt,Trash2) Forc = ResultVecA(XYear) if (LastEffClimSens.NE.MissVal.AND.DTDt.NE.MissVal) then EffClimSens = LastEffClimSens + (DTDt * FitAlpha * exp (FitBeta * DTDt)) ! calculates eff.clim.sens. LastEffClimSens = EffClimSens end if if (EffClimSens.NE.MissVal.AND.Forc.NE.MissVal) & Data(XYear,NextFree) = EffClimSens * (Forc / Forc2co2) ! calcs equilibrium T end do deallocate (LSRExe,LSRWye,OpVec,ResultVecA,ResultVecB,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcEquT: Deallocation failure #####" call StoreMoveOn print* end subroutine CalcEquT !******************************************************************************* subroutine PrintPeriodMean print*, " > Select first, last years AD in period: " do read (*,*,iostat=ReadStatus), BaseADYear0,BaseADYear1 if (ReadStatus.LE.0.AND.BaseADYear0.GE.YearAD(1).AND.BaseADYear1.LE.YearAD(YearN) & .AND.BaseADYear1.GE.BaseADYear0) exit end do do XCol = 1, ColN OpTot = 0.0 ; OpEn = 0.0 ; OpMean = MissVal do XYear = 1, YearN if (YearAD(XYear).GE.BaseADYear0.AND.YearAD(XYear).LE.BaseADYear1) then if (Data(XYear,XCol).NE.MissVal) then OpTot = OpTot + Data(XYear,XCol) ; OpEn = OpEn + 1 end if end if end do if (OpEn.GE.1) OpMean = OpTot / OpEn print "(a,i3,2e12.4)", " ", XCol, OpMean, OpEn end do end subroutine PrintPeriodMean !******************************************************************************* ! select column subroutine SelectColumn print*, " > Select the column: " do read (*,*,iostat=ReadStatus), ChosenCol if (ReadStatus.LE.0 .AND. ChosenCol.GE.1 .AND. ChosenCol.LE.ColN) exit end do end subroutine SelectColumn !******************************************************************************* ! store data in column and move on subroutine StoreMoveOn call CheckBlank if (NonBlank.EQ.0) then print*, " > Operation has no valid results. No results stored." else print "(a13,i4,a9)", " > Column: ", NextFree, adjustr(ColTitles(NextFree)) NextFree = NextFree + 1 if (NextFree.GT.ColN) then NextFree = NextFree - 1 print*, " > All columns are being used. Next free set to: ", NextFree end if end if end subroutine StoreMoveOn !******************************************************************************* ! check whether column is (=0) or is not (=1) blank subroutine CheckBlank NonBlank = 0 XYear = 0 do XYear = XYear + 1 if (Data(XYear,NextFree).NE.MissVal) NonBlank = 1 if (NonBlank.EQ.1) exit if (XYear.EQ.YearN) exit end do end subroutine CheckBlank !******************************************************************************* ! save selected columns to .ann file subroutine DumpToAnn call CheckMaster if (ColN.GT.1) then print*, " > Enter the number of columns to save to .ann: " do read (*,*,iostat=ReadStatus), SaveColN if (ReadStatus.LE.0 .AND. SaveColN.GE.1 .AND. SaveColN.LE.ColN) exit end do else SaveColN = 1 end if allocate ( FileData (YearN, SaveColN), & FileColTitles (SaveColN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DumpToAnn: Allocation failure #####" if (SaveColN.LT.ColN) print "(a,i4)", " > Select each column from array in turn: " do XSaveCol = 1, SaveColN if (SaveColN.LT.ColN) then do read (*,*,iostat=ReadStatus), ChosenCol if (ReadStatus.GT.0 .OR. ChosenCol.LT.1 .OR. ChosenCol.GT.ColN) print*, " > Bad entry. Try again." if (ReadStatus.LE.0 .AND. ChosenCol.GE.1 .AND. ChosenCol.LE.ColN) exit end do else ChosenCol = XSaveCol end if FileColTitles(XSaveCol) = ColTitles(ChosenCol) do XYear = 1, YearN FileData(XYear,XSaveCol) = Data(XYear,ChosenCol) end do end do call MakeANNColTitles (FileColTitles) call SaveANN (Blank, YearAD, FileColTitles, FileData) print* deallocate (FileColTitles,FileData, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DumpToAnn: Deallocation failure #####" end subroutine DumpToAnn !******************************************************************************* ! conclude subroutine Conclude deallocate (YearAD,Data,ColTitles,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: Conclude: Deallocation failure #####" close (99) print* end subroutine Conclude !******************************************************************************* end program OpAnn