! seqtim.f90 ! f90 main program written on 19.06.00 by Tim Mitchell ! last modification on 26.09.00 ! f90 -o ./../goglo/seqtim initialmod.f90 loadmod.f90 savemod.f90 transformmod.f90 sortmod.f90 ! basicfun.f90 slicestats.f90 scalemod.f90 trendsmod.f90 arraymod.f90 ./../goglo/seqtim.f90 ! purpose is to permit us to avoid multiple saves to .tim and truncations to zero program SeqTim use InitialMod use LoadMod use SaveMod use TransformMod use SortMod use BasicFun use SliceStats use ScaleMod use TrendsMod use ArrayMod implicit none real, pointer, dimension (:,:,:) :: TimLoaded real, pointer, dimension (:,:) :: TimSaved, ThisTim, LinLoaded, LinSaved real, pointer, dimension (:,:) :: ExeSeries, WyeSeries, OperationKey, OpTim real, pointer, dimension (:) :: Vectorised, GloLoaded, FunData, OperationRes, YearVec real, pointer, dimension (:) :: AyeKay, BeeKay, AreKay, LoPass, HiPass real, pointer, dimension (:) :: ExeLine, WyeLine, WyeFit, Bases, Chunks integer, pointer, dimension (:) :: WorkMapRawReg, WorkRegSizes, WorkADYear, UseReg integer, pointer, dimension (:) :: NewMapRawReg, NewRegSizes integer, pointer, dimension (:,:) :: WorkMapIDLRaw, WorkMapIDLReg, NewMapIDLReg character (len=20), pointer, dimension (:) :: WorkRegNames, NewRegNames character (len=80), pointer, dimension (:) :: ThisNames real, allocatable, dimension (:,:) :: NewTot, NewEn integer, allocatable, dimension (:) :: UseTim, RegSame, YearSame real, parameter :: MissVal = -999.0 real :: MissAccept real :: RunTot, RunEn, RunSqTot real :: Aye, Bee, Are, Num, Den real :: SumX, SumY, SumXX, SumYY, SumXY, En real :: OpTot, OpSqTot, OpEn, OpMean, OpStDev real :: RegSqTot, RegTot, RegEn, RegMean, RegStDev, RegRMSE real :: CutOffVal, TestVal, ChosenKay, RealConstant real :: RegThresh real :: ValueA, ValueB integer :: WorkGrid, WorkLongN, WorkLatN, WorkDataN integer :: WorkMonth0,WorkMonth1,WorkMonthN,WorkYearN,WorkDecN integer :: WorkRegN, WorkTimN, ThisRegN, NewRegN integer :: SelectTimN, ChosenTim, BlankColN, AllColUsed, LastColUsed integer :: AllocStat, ReadStatus, ValidTot integer :: XReg, XGlo, XTimFree, XTimSave, XSelect, XTim, XYear, XLine, XOperation, XFile, XLong, XLat integer :: QAnom, QMain, QSampPop, QConBee, QColEns, QStatistic, QKayTot, QConvert, QWeight, QKeepMiss integer :: QDeTrend integer :: CutOffSign, CutOffType, RegKept, RegCutOff integer :: ChosenExp, Operator, IntConstant integer :: SliceLen, OperationN integer :: ThisLinN, XSelectLin integer :: SelectReg, SelectRegN, SelTim integer :: EnsRegSame, EnsYearSame integer :: GloFileN, LinFileN integer :: Iter, Log, PerLen, GapLen, Offset, Year0, Year1 character (len=10) :: WorkGridTitle character (len=40) :: WorkRegTitle, NewRegTitle character (len=80) :: WorkGridFilePath, Blank !******************************************************************************* ! initialise open (99,file="/cru/u2/f709762/data/scratch/log-seqtim.dat",status="replace",action="write") print*, " > ***** SeqTim *****" print* Blank = "" MissAccept = 10 AllColUsed = 0 call GridSelect (WorkGrid,WorkGridTitle,WorkLongN,WorkLatN,WorkDataN,WorkGridFilePath) call RegSelect (WorkGrid,WorkLongN,WorkLatN,WorkDataN,WorkMapIDLReg,WorkRegSizes,WorkRegNames,& WorkRegTitle,WorkRegN) call PeriodSelect(WorkYearN,WorkDecN,WorkADYear) call GrabTim QMain = -1 do if (QMain.EQ.-1) then else if (QMain.EQ.0) then call SetMissAccept (MissAccept) else if (QMain.EQ.1) then call SelectTimOpN call SelectTimOp call CalcMean else if (QMain.EQ.2) then call SelectTimOpN call SelectTimOp call CalcStDev else if (QMain.EQ.3) then SelectTimN = 2 call SelectTimOp call CalcLSRReg else if (QMain.EQ.4) then SelectTimN = 1 call SelectTimOp call DeTrendA else if (QMain.EQ.5) then SelectTimN = 1 call SelectTimOp call GlobalMean else if (QMain.EQ.6) then SelectTimN = 3 call SelectTimOp call PosABC else if (QMain.EQ.7) then SelectTimN = 2 call SelectTimOp call MaskAB else if (QMain.EQ.8) then SelectTimN = 1 call SelectTimOp call OperateAConstant else if (QMain.EQ.9) then SelectTimN = 2 call SelectTimOp call OperateAB else if (QMain.EQ.10) then call ClearLastCol else if (QMain.EQ.11) then call GrabGlo else if (QMain.EQ.12) then call GrabLin else if (QMain.EQ.13) then SelectTimN = 1 call SelectTimOp call ExtractTrendA else if (QMain.EQ.14) then SelectTimN = 1 call SelectTimOp call StDevChunks else if (QMain.EQ.20) then SelectTimN = 1 call SelectTimOp call SaveToTim else if (QMain.EQ.21) then SelectTimN = 1 call SelectTimOp call SaveSlices else if (QMain.EQ.22) then SelectTimN = 1 call SelectTimOp call SaveRegions else if (QMain.EQ.23) then SelectTimN = 1 call SelectTimOp call SaveGlobalMean else if (QMain.EQ.24) then SelectTimN = 1 call SelectTimOp call ConvertA else if (QMain.EQ.30) then call PrintToScreen else if (QMain.EQ.40) then call SequenceOp else if (QMain.EQ.50) then call SelectTimOpN call SelectTimOp call SlicePerMom else if (QMain.EQ.51) then SelectTimN = 1 call SelectTimOp call GaussSmoothA else if (QMain.EQ.52) then SelectTimN = 1 call SelectTimOp call AnomAPerA else print*, " > Select the comparison to make: " print*, " > 0. Change % acceptable missing, currently: ", MissAccept print*, " > 1. Mean of multiple A" print*, " > 2. Stdev of multiple A" print*, " > 3. LSR of each region in A(x) with B(y)" print*, " > 4. Detrend A" print*, " > 5. Global-mean of A, filling col" print*, " > 6. Position of A relative to B, C" print*, " > 7. Mask A using B" print*, " > 8. Operate on A with k" print*, " > 9. Operate on A with B" print*, " > 10. Clear last column filled" print*, " > 11. Fill columns with .glo files" print*, " > 12. Fill columns with .lin files" print*, " > 13. Robust trend for each region in A" print*, " > 14. Calc stdev of chunks from A -> .glo" print*, " > 20. Save A to .tim" print*, " > 21. Save year slices from A to .glo" print*, " > 22. Save regions from A to .lin" print*, " > 23. Save global mean from A to .lin" print*, " > 24. Convert A to another region set, to .tim" print*, " > 30. Print stats for all to screen" print*, " > 40. Perform sequence of operations" print*, " > 50. Sliceify on A,B,... for per k (any moment)" print*, " > 51. Smooth A with Gaussian filter" print*, " > 52. Anomalise A using period from A" print*, " > 99. Exit." end if if (allocated(UseTim)) deallocate (UseTim, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: Main: Deallocation failure #####" print* print*, " > Main menu: select option: " do read (*,*,iostat=ReadStatus), QMain if (ReadStatus.LE.0) exit end do if (QMain.EQ.99) exit end do deallocate (TimLoaded,RegSame,YearSame) deallocate (WorkMapIDLReg,WorkRegSizes,WorkRegNames) print* close (99) contains !******************************************************************************* ! load .tim subroutine GrabTim BlankColN = 10 print*, " > Select the number of .tim to load: " do read (*,*,iostat=ReadStatus), WorkTimN if (ReadStatus.LE.0.AND.WorkTimN.GE.0) exit end do print*, " > Specify the number of blank columns: " do read (*,*,iostat=ReadStatus), BlankColN if (ReadStatus.LE.0.AND.BlankColN.GE.0) exit end do XTimFree = WorkTimN + 1 WorkTimN = WorkTimN + BlankColN allocate (TimLoaded(WorkTimN,WorkRegN,WorkYearN), & RegSame (WorkTimN), & YearSame (WorkTimN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GrabTim: Allocation failure #####" TimLoaded = MissVal RegSame = 0 YearSame = 0 do XTim = 1, (WorkTimN-BlankColN) print*, " > Load .tim number ", XTim call LoadTim (WorkYearN,WorkADYear,ThisRegN,ThisNames,ThisTim) if (ThisRegN.NE.WorkRegN) print*, " > ##### ERROR: GrabTim: incorrect no. of regions in file #####" do XYear = 1, WorkYearN do XReg = 1, WorkRegN TimLoaded (XTim,XReg,XYear) = ThisTim (XReg,XYear) end do end do deallocate (ThisTim,ThisNames, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GrabTim: Deallocation failure #####" end do end subroutine GrabTim !******************************************************************************* ! select number of .glo subroutine SelectTimOpN print*, " > Select the number of .tim to use." do read (*,*,iostat=ReadStatus), SelectTimN if (ReadStatus.LE.0.AND.SelectTimN.GE.1) exit end do end subroutine SelectTimOpN !******************************************************************************* ! select particular .tim to use subroutine SelectTimOp allocate (UseTim(SelectTimN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SelectTimOp: Allocation failure #####" UseTim = 0 if (AllColUsed.EQ.0) then LastColUsed = XTimFree - 1 else LastColUsed = XTimFree end if print*, " > Select particular .tim to use in op, totalling: ", SelectTimN do XSelect = 1, SelectTimN print*, " > Select .tim number: ", XSelect do read (*,*,iostat=ReadStatus), ChosenTim if (ReadStatus.LE.0.AND.ChosenTim.GE.1.AND.ChosenTim.LE.LastColUsed) exit end do UseTim (XSelect) = ChosenTim end do end subroutine SelectTimOp !******************************************************************************* ! calc Mean subroutine CalcMean print*, " > Calculating..." allocate (FunData(SelectTimN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcMean: Allocation failure #####" do XReg = 1, WorkRegN do XYear = 1, WorkYearN do XTim = 1, SelectTimN FunData (XTim) = TimLoaded(UseTim(XTim),XReg,XYear) end do TimLoaded (XTimFree,XReg,XYear) = OpCalcMean (FunData,SelectTimN,MissAccept) end do end do deallocate (FunData, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcMean: Deallocation failure #####" call AlertMiss end subroutine CalcMean !******************************************************************************* ! calc StDev subroutine CalcStDev allocate (FunData(SelectTimN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcStDev: Allocation failure #####" if (WorkTimN.GE.2) then print*, " > Calc sample (=1) or population (=2) stdev ?" do read (*,*,iostat=ReadStatus), QSampPop if (ReadStatus.LE.0 .AND. QSampPop.GE.1 .AND. QSampPop.LE.2) exit end do print*, " > Calculating..." do XReg = 1, WorkRegN do XYear = 1, WorkYearN do XTim = 1, SelectTimN FunData (XTim) = TimLoaded(UseTim(XTim),XReg,XYear) end do TimLoaded (XTimFree,XReg,XYear) = OpCalcStDev (FunData,SelectTimN,MissAccept,QSampPop) end do end do call AlertMiss else print*, " > Insufficient .tim selected." end if deallocate (FunData, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcStDev: Deallocation failure #####" end subroutine CalcStDev !******************************************************************************* ! calc LSR between regions in A(x) and B(y) subroutine CalcLSRReg print*, " > Regress for y=ax (=1) or y=ax+b (=2) ? " do read (*,*,iostat=ReadStatus), QKayTot if (ReadStatus.LE.0.AND.QKayTot.GE.1.AND.QKayTot.LE.2) exit end do allocate (WyeSeries(1,WorkYearN), & ExeSeries(1,WorkYearN), & AyeKay (WorkRegN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcLSRReg: Allocation failure #####" if (QKayTot.Eq.2) then allocate (BeeKay (WorkRegN), & AreKay (WorkRegN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcLSRReg: Allocation failure #####" end if print*, " > Calculating..." do XReg = 1, WorkRegN do XYear = 1, WorkYearN ExeSeries (1,XYear) = TimLoaded(UseTim(1),XReg,XYear) WyeSeries (1,XYear) = TimLoaded(UseTim(2),XReg,XYear) end do if (QKayTot.EQ.1) then call LinearLSRZero (1,WorkYearN,ExeSeries,WyeSeries,Aye) AyeKay (XReg) = Aye else call LinearLSR (1,WorkYearN,ExeSeries,WyeSeries,Aye,Bee,Are) AyeKay (XReg) = Aye BeeKay (XReg) = Bee AreKay (XReg) = Are end if end do print*, " > Save 'a'." call SaveGlo (WorkLongN, WorkLatN, WorkRegN, WorkGridFilePath, Blank, Blank, AyeKay, WorkMapIDLReg) if (QKayTot.Eq.2) then print*, " > Save 'b'." call SaveGlo (WorkLongN, WorkLatN, WorkRegN, WorkGridFilePath, Blank, Blank, BeeKay, WorkMapIDLReg) print*, " > Save 'r'." call SaveGlo (WorkLongN, WorkLatN, WorkRegN, WorkGridFilePath, Blank, Blank, AreKay, WorkMapIDLReg) end if if (QKayTot.Eq.2) then deallocate (BeeKay,AreKay, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcLSRReg: Deallocation failure #####" end if deallocate (WyeSeries,ExeSeries,AyeKay, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: CalcLSRReg: Deallocation failure #####" end subroutine CalcLSRReg !******************************************************************************* ! calc global mean and fill column with it subroutine DeTrendA allocate (ThisTim(WorkRegN,WorkYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DeTrendA: Allocation failure #####" do XReg = 1, WorkRegN do XYear = 1, WorkYearN ThisTim (XReg,XYear) = TimLoaded(UseTim(1),XReg,XYear) end do end do call DeTrendTim (WorkRegN,WorkYearN,MissAccept,1,WorkADYear,ThisTim,AyeKay,BeeKay) do XReg = 1, WorkRegN do XYear = 1, WorkYearN TimLoaded(XTimFree,XReg,XYear) = ThisTim (XReg,XYear) end do end do call AlertMiss deallocate (ThisTim, AyeKay, BeeKay, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: DeTrendA: Deallocation failure #####" end subroutine DeTrendA !******************************************************************************* ! extract trend (y=ax+b) from each region ! uses robust method of LSR subroutine ExtractTrendA allocate (ExeLine(WorkYearN), & WyeLine(WorkYearN), & AyeKay (WorkRegN), & BeeKay (WorkRegN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ExtractTrendA: Allocation failure #####" do XYear = 1, WorkYearN ! get years ExeLine (XYear) = real (WorkADYear (XYear)) end do print*, " > Calculating..." do XReg = 1, WorkRegN ! loop by region do XYear = 1, WorkYearN ! get region time Line WyeLine (XYear) = TimLoaded(UseTim(1),XReg,XYear) end do call RobustLSR (WorkYearN,ExeLine,WyeLine,WyeFit,Bee,Aye,Iter) ! reversal of Aye, Bee fits routine deallocate (WyeFit, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ExtractTrendA: Deallocation failure #####" AyeKay(XReg) = Aye BeeKay(XReg) = Bee end do print*, " > Save 'a' from y=ax+b to .glo." call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGridFilePath,Blank,Blank,AyeKay,WorkMapIDLReg) print*, " > Save 'b' from y=ax+b to .glo." call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGridFilePath,Blank,Blank,BeeKay,WorkMapIDLReg) deallocate (ExeLine,WyeLine,AyeKay,BeeKay, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ExtractTrendA: Deallocation failure #####" end subroutine ExtractTrendA !******************************************************************************* subroutine StDevChunks print*, " > Enter the offset from the start to omit (>=0): " do read (*,*,iostat=ReadStatus), Offset if (ReadStatus.LE.0.AND.Offset.GE.0.AND.Offset.LT.WorkYearN) exit end do print*, " > Enter the length of chunk and of gap: " do read (*,*,iostat=ReadStatus), PerLen, GapLen if (ReadStatus.LE.0.AND.PerLen.GT.0.AND.PerLen.LE.WorkYearN.AND.GapLen.GE.0) exit end do print*, " > Calculate sample (=1) or population (=2) stdev ? " do read (*,*,iostat=ReadStatus), QSampPop if (ReadStatus.LE.0.AND.QSampPop.GE.1.AND.QSampPop.LE.2) exit end do allocate (Vectorised(WorkYearN), & GloLoaded(WorkRegN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: StDevChunks: Allocation failure #####" do XReg = 1, WorkRegN do XYear = 1, WorkYearN Vectorised (XYear) = TimLoaded(UseTim(1),XReg,XYear) end do call GetChunkMeans (Vectorised,Chunks,Offset,PerLen,GapLen,MissAccept) GloLoaded(XReg) = OpCalcStDev (Chunks, nint(MissVal), MissAccept, QSampPop) deallocate (Chunks,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: StDevChunks: Deallocation failure #####" end do call SaveGlo (WorkLongN,WorkLatN,WorkRegN,WorkGridFilePath,Blank,Blank,GloLoaded,WorkMapIDLReg) deallocate (Vectorised,GloLoaded,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: StDevChunks: Deallocation failure #####" end subroutine StDevChunks !******************************************************************************* ! calc global mean and fill column with it subroutine GlobalMean print*, " > Calculate unweighted (=1) or weighted (=2) mean ? " do read (*,*,iostat=ReadStatus), QWeight if (ReadStatus.LE.0.AND.QWeight.GE.1.AND.QWeight.LE.2) exit end do if (QWeight.EQ.2) then print*, " > Load .glo file containing weights: " call LoadGlo (WorkLongN, WorkLatN, WorkRegN, WorkMapIDLReg, GloLoaded) end if allocate (FunData(WorkRegN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GlobalMean: Allocation failure #####" print*, " > Calculating..." do XYear = 1, WorkYearN if (YearSame(UseTim(1)).NE.1.OR.XYear.EQ.1) then do XReg = 1, WorkRegN FunData (XReg) = TimLoaded(UseTim(1),XReg,XYear) end do if (QWeight.EQ.1) OpMean = OpCalcMean (FunData,WorkRegN,MissAccept) if (QWeight.EQ.2) OpMean = OpWeightedMean (FunData,GloLoaded,WorkRegN,MissAccept) end if do XReg = 1, WorkRegN TimLoaded (XTimFree,XReg,XYear) = OpMean end do end do RegSame (XTimFree) = 1 YearSame (XTimFree) = 0 if (QWeight.EQ.2) then deallocate (GloLoaded, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GlobalMean: Deallocation failure #####" end if deallocate (FunData, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GlobalMean: Deallocation failure #####" call AlertMiss end subroutine GlobalMean !******************************************************************************* ! pos of A relative to B and C subroutine PosABC print*, " > Calculating..." do XReg = 1, WorkRegN do XYear = 1, WorkYearN if (TimLoaded(UseTim(1),XReg,XYear).NE.MissVal.AND.TimLoaded(UseTim(2),XReg,XYear).NE.MissVal & .AND.TimLoaded(UseTim(3),XReg,XYear).NE.MissVal) then if (TimLoaded(UseTim(1),XReg,XYear).LT.TimLoaded(UseTim(2),XReg,XYear) & .AND.TimLoaded(UseTim(1),XReg,XYear).LT.TimLoaded(UseTim(3),XReg,XYear)) then TimLoaded (XTimFree,XReg,XYear) = -1 else if (TimLoaded(1,XReg,XYear).GT.TimLoaded(UseTim(2),XReg,XYear) & .AND.TimLoaded(UseTim(1),XReg,XYear).GT.TimLoaded(UseTim(3),XReg,XYear)) then TimLoaded (XTimFree,XReg,XYear) = 1 else TimLoaded (XTimFree,XReg,XYear) = 0 end if else TimLoaded (XTimFree,XReg,XYear) = MissVal end if end do end do call AlertMiss end subroutine PosABC !******************************************************************************* ! mask A using B subroutine MaskAB print*, " > Is the threshold a real (=1) or a magnitude (=2): " do read (*,*,iostat=ReadStatus), CutOffType if (ReadStatus.LE.0.AND.CutOffType.GE.1.AND.CutOffType.LE.2) exit end do print*, " > Enter the threshold in B beyond which to set A to missing: " do read (*,*,iostat=ReadStatus), CutOffVal if (ReadStatus.LE.0) exit end do print*, " > Cut off values smaller (=1) or greater (=2) than: ", CutOffVal do read (*,*,iostat=ReadStatus), CutOffSign if (ReadStatus.LE.0.AND.CutOffSign.GE.1.AND.CutOffSign.LE.2) exit end do print*, " > Calculating..." RegKept = 0 RegCutOff = 0 do XReg = 1, WorkRegN do XYear = 1, WorkYearN if (TimLoaded(UseTim(1),XReg,XYear).NE.MissVal.AND.TimLoaded(UseTim(2),XReg,XYear).NE.MissVal) then if (CutOffType.EQ.2) then TestVal = abs (TimLoaded(UseTim(2),XReg,XYear)) else TestVal = TimLoaded(UseTim(2),XReg,XYear) end if if (TestVal.LT.CutOffVal.AND.CutOffSign.EQ.1) then TimLoaded (XTimFree,XReg,XYear) = MissVal RegCutOff = RegCutOff + 1 else if (TestVal.GT.CutOffVal.AND.CutOffSign.EQ.2) then TimLoaded (XTimFree,XReg,XYear) = MissVal RegCutOff = RegCutOff + 1 else TimLoaded (XTimFree,XReg,XYear) = TimLoaded(UseTim(1),XReg,XYear) RegKept = RegKept + 1 end if else TimLoaded (XTimFree,XReg,XYear) = MissVal end if end do end do print*, " > Region-years kept, cut off: ", RegKept, RegCutOff call AlertMiss end subroutine MaskAB !******************************************************************************* ! divide by constant subroutine OperateAConstant call OpAKayOptions print*, " > Calculating..." do XReg = 1, WorkRegN do XYear = 1, WorkYearN TimLoaded (XTimFree,XReg,XYear) = OpAwithB (TimLoaded(UseTim(1),XReg,XYear),RealConstant,Operator) end do end do call AlertMiss end subroutine OperateAConstant !******************************************************************************* subroutine OpAKayOptions print*, " > Divide =1, times =2, minus =3, add =4, sqroot =5, expon =6, abs =7" do read (*,*,iostat=ReadStatus), Operator if (ReadStatus.LE.0 .AND. Operator.GE.1 .AND. Operator.LE.7) exit end do if (Operator.LT.5) then print*, " > Enter constant (real):" do read (*,*,iostat=ReadStatus), RealConstant if (ReadStatus.LE.0) exit end do else if (Operator.EQ.5) then RealConstant = 0 else if (Operator.EQ.6) then print*, " > Enter constant (integer):" do read (*,*,iostat=ReadStatus), RealConstant if (ReadStatus.LE.0) exit end do else if (Operator.EQ.7) then RealConstant = 0 end if end subroutine OpAKayOptions !******************************************************************************* ! operate on A with B subroutine OperateAB call OpABOptions print*, " > Calculating..." do XReg = 1, WorkRegN do XYear = 1, WorkYearN TimLoaded (XTimFree,XReg,XYear) = OpAwithB (TimLoaded(UseTim(1),XReg,XYear), & TimLoaded(UseTim(2),XReg,XYear),Operator) end do end do call AlertMiss end subroutine OperateAB !******************************************************************************* ! operate on A with B subroutine OpABOptions print*, " > A operator B" print*, " > Operator is divide =1, multi =2, minus =3, add =4" do read (*,*,iostat=ReadStatus), Operator if (ReadStatus.LE.0 .AND. Operator.GE.1 .AND. Operator.LE.4) exit end do end subroutine OpABOptions !******************************************************************************* ! clear last column subroutine ClearLastCol do XReg = 1, WorkRegN do XYear = 1, WorkYearN TimLoaded ((XTimFree-1),XReg,XYear) = MissVal end do end do XTimFree = XTimFree - 1 print*, " > Column cleared and made next free: ", XTimFree end subroutine ClearLastCol !******************************************************************************* ! fill column with .glo subroutine GrabGlo print*, " > Enter the number of .glo files to load: " do read (*,*,iostat=ReadStatus), GloFileN if (ReadStatus.LE.0 .AND. GloFileN.GE.0) exit end do do XFile = 1, GloFileN print*, " > Load .glo file: ", XFile call LoadGlo (WorkLongN, WorkLatN, WorkRegN, WorkMapIDLReg, GloLoaded) do XReg = 1, WorkRegN do XYear = 1, WorkYearN TimLoaded (XTimFree,XReg,XYear) = GloLoaded (XReg) end do end do YearSame (XTimFree) = 1 ! denotes that entire column has identical years RegSame (XTimFree) = 0 deallocate (GloLoaded, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GrabLin: Deallocation failure #####" call AlertMiss end do end subroutine GrabGlo !******************************************************************************* ! fill column with .lin subroutine GrabLin print*, " > Enter the number of .lin files to load: " do read (*,*,iostat=ReadStatus), LinFileN if (ReadStatus.LE.0 .AND. LinFileN.GE.0) exit end do do XFile = 1, LinFileN print*, " > Load .lin file: ", XFile call LoadLin (WorkYearN, WorkADYear, ThisLinN, ThisNames, LinLoaded) if (ThisLinN.EQ.1) then XSelectLin = 1 else print*, " > Enter the index of the line to adopt as the scalar (0=list):" do do read (*,*,iostat=ReadStatus), XSelectLin if (ReadStatus.LE.0 .AND. XSelectLin.GE.0 .AND. XSelectLin .LE. ThisLinN) exit end do if (XSelectLin.EQ.0) then do XLine = 1, ThisLinN print*, XLine, ThisNames(XLine) end do end if if (XSelectLin.GT.0) exit end do end if do XReg = 1, WorkRegN do XYear = 1, WorkYearN TimLoaded (XTimFree,XReg,XYear) = LinLoaded (XSelectLin,XYear) end do end do RegSame (XTimFree) = 1 ! denotes that entire column has identical regions YearSame (XTimFree) = 0 deallocate (ThisNames,LinLoaded, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GrabLin: Deallocation failure #####" call AlertMiss end do end subroutine GrabLin !******************************************************************************* ! save .tim file subroutine SaveToTim allocate (TimSaved(WorkRegN,WorkYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SaveToTim: Allocation failure #####" TimSaved = MissVal do XYear = 1, WorkYearN do XReg = 1, WorkRegN TimSaved(XReg,XYear) = TimLoaded(UseTim(1),XReg,XYear) end do end do call SaveTim (WorkRegN, WorkYearN, Blank, Blank, WorkRegNames, WorkADYear, TimSaved) deallocate (TimSaved, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SaveToTim: Deallocation failure #####" end subroutine SaveToTim !******************************************************************************* ! convert A to another region set and save to .tim ! WARNING: this will run, but not produce the right results, unless the old is one-region-per-box subroutine ConvertA call RegSelect (WorkGrid, WorkLongN, WorkLatN, WorkDataN, NewMapIDLReg, & NewRegSizes, NewRegNames, NewRegTitle, NewRegN) print*, " > Convert as totals (=1) or means (=2) ? " do read (*,*,iostat=ReadStatus), QConvert if (ReadStatus.LE.0.AND.QConvert.GE.1.AND.QConvert.LE.2) exit end do print*, " > Converting..." allocate (NewTot (NewRegN,WorkYearN), & NewEn (NewRegN,WorkYearN), & TimSaved (NewRegN,WorkYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertA: Allocation failure #####" NewTot = 0.0 NewEn = 0.0 TimSaved = MissVal do XLong = 1, WorkLongN do XLat = 1, WorkLatN if (NewMapIDLReg (XLong,XLat).NE.MissVal) then ! grid box is wanted for new region set if (WorkMapIDLReg (XLong,XLat).NE.MissVal) then ! grid box is specified in old region set do XYear = 1, WorkYearN if (TimLoaded (UseTim(1),WorkMapIDLReg(XLong,XLat),XYear).NE.MissVal) then ! value is valid NewTot (NewMapIDLReg(XLong,XLat),XYear) = NewTot (NewMapIDLReg(XLong,XLat),XYear) + & TimLoaded (UseTim(1),WorkMapIDLReg(XLong,XLat),XYear) NewEn (NewMapIDLReg(XLong,XLat),XYear) = NewEn (NewMapIDLReg(XLong,XLat),XYear) + 1.0 end if end do end if end if end do end do do XReg = 1, NewRegN do XYear = 1, WorkYearN if (NewEn(XReg,XYear).EQ.NewRegSizes(XReg)) then if (QConvert.EQ.1) then TimSaved (XReg,XYear) = NewTot (XReg,XYear) else TimSaved (XReg,XYear) = NewTot (XReg,XYear) / NewEn (XReg,XYear) end if end if end do end do call SaveTim (NewRegN, WorkYearN, Blank, Blank, NewRegNames, WorkADYear, TimSaved) deallocate (NewMapIDLReg, NewRegSizes, NewRegNames, NewTot, NewEn, TimSaved, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertA: Deallocation failure #####" end subroutine ConvertA !******************************************************************************* ! save specified slices to .glo subroutine SaveSlices allocate (OpTim (WorkRegN,WorkYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertGlo: Allocation failure #####" OpTim = MissVal do XReg = 1, WorkRegN do XYear = 1, WorkYearN OpTim (XReg,XYear) = TimLoaded(UseTim(1),XReg,XYear) end do end do call TimToGlo (WorkLongN, WorkLatN, WorkRegN, WorkYearN, WorkGridFilePath, & WorkADYear, WorkMapIDLReg, OpTim) deallocate (OpTim, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ConvertGlo: Deallocation failure #####" end subroutine SaveSlices !******************************************************************************* ! save specified regions to .lin subroutine SaveRegions allocate (UseReg (WorkRegN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SaveRegions: Allocation failure #####" UseReg = 0 if (WorkRegN.GT.1) then SelectRegN = 0 do print*, " > Specify a region to save (0=list,-1=end): " do read (*,*,iostat=ReadStatus), SelectReg if (ReadStatus.NE.0.OR.SelectReg.LT.-1.OR.SelectReg.GT.WorkRegN) print*, " > Unacceptable entry." if (ReadStatus.LE.0.AND.SelectReg.GE.-1.AND.SelectReg.LE.WorkRegN) exit end do if (SelectReg.EQ.0) then do XReg = 1, WorkRegN print "(i6,a1,a20)", XReg, " ", WorkRegNames(XReg) end do else if (SelectReg.GE.1.AND.SelectReg.LE.WorkRegN) then SelectRegN = SelectRegN + 1 UseReg (SelectRegN) = SelectReg print "(i6,a1,a20)", SelectReg, " ", WorkRegNames(SelectReg) else if (SelectReg.NE.-1) then print*, " > Unacceptable entry." end if if (SelectReg.EQ.-1.AND.SelectRegN.GE.1) exit end do else SelectRegN = 1 UseReg(1) = 1 end if allocate (LinSaved (SelectRegN,WorkYearN), & ThisNames(SelectRegN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SaveRegions: Allocation failure #####" LinSaved = MissVal do XReg = 1, SelectRegN ThisNames (XReg) = WorkRegNames (UseReg(XReg)) end do do XReg = 1, SelectRegN do XYear = 1, WorkYearN LinSaved (XReg,XYear) = TimLoaded (UseTim(1),UseReg(XReg),XYear) end do end do call SaveLin (SelectRegN, WorkYearN, ThisNames, WorkADYear, LinSaved) deallocate (LinSaved,ThisNames,UseReg, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SaveRegions: Deallocation failure #####" end subroutine SaveRegions !******************************************************************************* ! save global mean to .lin subroutine SaveGlobalMean print*, " > Calculate unweighted (=1) or weighted (=2) mean ? " do read (*,*,iostat=ReadStatus), QWeight if (ReadStatus.LE.0.AND.QWeight.GE.1.AND.QWeight.LE.2) exit end do if (QWeight.EQ.2) then print*, " > Load .glo file containing weights: " call LoadGlo (WorkLongN, WorkLatN, WorkRegN, WorkMapIDLReg, GloLoaded) end if allocate (LinSaved (1,WorkYearN), & ThisNames(1), & FunData(WorkRegN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SaveGlobalMean: Allocation failure #####" LinSaved = MissVal ThisNames(1) = "global mean" do XYear = 1, WorkYearN do XReg = 1, WorkRegN FunData (XReg) = TimLoaded(UseTim(1),XReg,XYear) end do if (QWeight.EQ.1) LinSaved (1,XYear) = OpCalcMean (FunData, WorkRegN,MissAccept) if (QWeight.EQ.2) LinSaved (1,XYear) = OpWeightedMean (FunData,GloLoaded,WorkRegN,MissAccept) end do call SaveLin (1, WorkYearN, ThisNames, WorkADYear, LinSaved) if (QWeight.EQ.2) then deallocate (GloLoaded, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SaveGlobalMean: Deallocation failure #####" end if deallocate (LinSaved,ThisNames,FunData, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SaveGlobalMean: Deallocation failure #####" end subroutine SaveGlobalMean !******************************************************************************* ! print details to screen subroutine PrintToScreen print "(a4,5a12)", " Col", " Year-Reg.", " Sum", " Sum Squares", " Mean", " StDev" do XTim = 1, (XTimFree-1) OpTot = 0.0 OpSqTot = 0.0 OpEn = 0.0 OpMean = MissVal OpStDev = MissVal do XYear = 1, WorkYearN do XReg = 1, WorkRegN if (TimLoaded(XTim,XReg,XYear).NE.MissVal) then OpTot = OpTot + TimLoaded(XTim,XReg,XYear) OpSqTot = OpSqTot + (TimLoaded(XTim,XReg,XYear) ** 2) OpEn = OpEn + 1.0 end if end do end do if (OpEn.GE.1) then OpMean = OpTot / OpEn OpStDev = (OpSqTot / OpEn) - (OpMean ** 2) OpStDev = sqrt (OpStDev) end if print "(i4,5e12.4)", XTim, OpEn, OpTot, OpSqTot, OpMean, OpStDev end do end subroutine PrintToScreen !******************************************************************************* ! sequence of operations subroutine SequenceOp print*, " > Enter the number of operations: " do read (*,*,iostat=ReadStatus), OperationN if (ReadStatus.LE.0.AND.OperationN.GE.1) exit end do allocate (OperationKey (OperationN,4), & OperationRes (OperationN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SequenceOp: Allocation failure #####" print*, " > DEFINE OPERATIONS." do XOperation = 1, OperationN print*, " > Operation: ", XOperation print*, " > Operate on A with constant (=8) or B (=9): " do read (*,*,iostat=ReadStatus), QConBee if (ReadStatus.LE.0.AND.QConBee.GE.8.AND.QConBee.LE.9) exit end do if (QConBee.EQ.8) then OperationKey (XOperation,1) = 8 print*, " > Select particular .tim A from either/or: " call SeqSelTim OperationKey (XOperation,2) = SelTim call OpAKayOptions OperationKey (XOperation,3) = RealConstant OperationKey (XOperation,4) = Operator else if (QConBee.EQ.9) then OperationKey (XOperation,1) = 9 print*, " > Select particular .tim A from either/or: " call SeqSelTim OperationKey (XOperation,2) = SelTim call OpABOptions OperationKey (XOperation,4) = Operator print*, " > Select particular .tim B from either/or: " call SeqSelTim OperationKey (XOperation,3) = SelTim end if end do print*, " > Calculating..." do XReg = 1, WorkRegN do XYear = 1, WorkYearN OperationRes = MissVal do XOperation = 1, OperationN if (OperationKey(XOperation,2).LE.WorkTimN) then ! value A ValueA = TimLoaded (OperationKey(XOperation,2),XReg,XYear) else ValueA = OperationRes ((OperationKey(XOperation,2)-WorkTimN)) end if if (OperationKey(XOperation,1).EQ.9) then ! value B or constant if (OperationKey(XOperation,3).LE.WorkTimN) then ValueB = TimLoaded (OperationKey(XOperation,3),XReg,XYear) else ValueB = OperationRes ((OperationKey(XOperation,3)-WorkTimN)) end if else ValueB = OperationKey(XOperation,3) end if Operator = nint(OperationKey(XOperation,4)) OperationRes (XOperation) = OpAwithB (ValueA,ValueB,Operator) ! operation end do TimLoaded (XTimFree,XReg,XYear) = OperationRes (OperationN) ! final value end do end do print*, " > We have stored the result in column: ", XTimFree if (XTimFree.EQ.WorkTimN) AllColUsed = 1 if (XTimFree.LT.WorkTimN) XTimFree = XTimFree + 1 deallocate (OperationKey,OperationRes, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SequenceOp: Deallocation failure #####" end subroutine SequenceOp !******************************************************************************* ! sequence of operations subroutine SeqSelTim print*, " > .tim in main (usual no), this seq output (op no + ", WorkTimN do read (*,*,iostat=ReadStatus), SelTim if (ReadStatus.LE.0.AND.SelTim.GE.1.AND.SelTim.LT.(WorkTimN+XOperation)) exit end do end subroutine SeqSelTim !******************************************************************************* ! alert to all MissVal in latest column subroutine AlertMiss ValidTot = 0 XReg = 0 do XReg = XReg + 1 XYear = 0 do XYear = XYear + 1 if (TimLoaded(XTimFree,XReg,XYear).NE.MissVal) ValidTot = ValidTot + 1 if (ValidTot.GT.0) exit if (XYear.EQ.WorkYearN) exit end do if (ValidTot.GT.0) exit if (XReg.EQ.WorkRegN) exit end do if (ValidTot.GT.0) then print*, " > We have filled column: ", XTimFree if (XTimFree.EQ.WorkTimN) AllColUsed = 1 if (XTimFree.LT.WorkTimN) XTimFree = XTimFree + 1 else print*, " > @@@@@ All column missing, so left unfilled. @@@@@" RegSame (XTimFree) = 0 YearSame (XTimFree) = 0 end if end subroutine AlertMiss !******************************************************************************* ! sliceify A,B,... by per k into any statistic ! median, mean, variance are calc as sample stats in usual manner ! skewness = (3*(mean--median))/stdev (Francis p88): <0=left skew=neg skew >0=opposite 0=normal ! kurtosis = (fourth moment/(second moment**2))--3 (Francis p88) -30=leptokurtic 0=normal subroutine SlicePerMom print*, " > Enter the slice length:" do read (*,*,iostat=ReadStatus), SliceLen if (ReadStatus.LE.0.AND.SliceLen.GE.2.AND.SliceLen.LT.WorkYearN) exit end do print*, " > Enter the statistic to calc for each slice:" print*, " > 0=median,1=mean,2=variance,3=skewness,4=kurtosis" do read (*,*,iostat=ReadStatus), QStatistic if (ReadStatus.LE.0.AND.QStatistic.GE.0.AND.QStatistic.LE.4) exit end do print*, " > Detrend each slice before calculating moment ? (1=no,2=yes)" do read (*,*,iostat=ReadStatus), QDeTrend if (ReadStatus.LE.0.AND.QDeTrend.GE.1.AND.QDeTrend.LE.2) exit end do if (SelectTimN.GT.1) then print*, " > Calc for each column individually (=1), or as ensemble (=2) ?" do read (*,*,iostat=ReadStatus), QColEns if (ReadStatus.LE.0.AND.QColEns.GE.1.AND.QColEns.LE.2) exit end do else QColEns = 1 end if if (QColEns.EQ.1) call SlicePerCol if (QColEns.EQ.2) call SlicePerEns end subroutine SlicePerMom !******************************************************************************* ! sliceify A,B,... by per k as columns subroutine SlicePerCol print*, " > Sliceifying each column and region..." allocate (Vectorised (WorkYearN), & YearVec (WorkYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SlicePerCol: Allocation failure #####" do XTim = 1, SelectTimN do XReg = 1, WorkRegN if (XReg.EQ.1.OR.RegSame(UseTim(XTim)).EQ.0) then do XYear = 1, WorkYearN Vectorised (XYear) = TimLoaded (UseTim(XTim),XReg,XYear) YearVec (XYear) = real (WorkADYear(XYear)) end do if (QDeTrend.EQ.2) call DeTrendCol (YearVec,Vectorised) call SliceStatistics (WorkYearN,SliceLen,QStatistic,MissAccept,Vectorised) end if do XYear = 1, WorkYearN TimLoaded (XTimFree,XReg,XYear) = Vectorised (XYear) end do end do print*, " > Have sliced col: ", UseTim(XTim), " into: ", XTimFree if (RegSame(UseTim(XTim)).EQ.1) then RegSame (XTimFree) = 1 else RegSame (XTimFree) = 0 end if YearSame (XTimFree) = 0 if (XTimFree.EQ.WorkTimN) AllColUsed = 1 if (XTimFree.LT.WorkTimN) XTimFree = XTimFree + 1 end do deallocate (Vectorised,YearVec, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SlicePerCol: Deallocation failure #####" end subroutine SlicePerCol !******************************************************************************* ! sliceify A,B,... by per k into stdev as ensemble subroutine SlicePerEns print*, " > Sliceifying the ensemble for each region..." allocate (OpTim (SelectTimN,WorkYearN), & Vectorised (WorkYearN), & YearVec (WorkYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SlicePerEns: Allocation failure #####" EnsRegSame = 1 do XTim = 1, SelectTimN if (RegSame(UseTim(XTim)).NE.1) EnsRegSame = EnsRegSame + 1 end do do XReg = 1, WorkRegN if (XReg.EQ.1.OR.EnsRegSame.NE.1) then Vectorised = MissVal do XTim = 1, SelectTimN do XYear = 1, WorkYearN OpTim (XTim,XYear) = TimLoaded (UseTim(XTim),XReg,XYear) YearVec (XYear) = real (WorkADYear(XYear)) end do end do if (QDeTrend.EQ.2) call DeTrendCol (YearVec,Vectorised) call SliceStatisticsEns (SelectTimN,WorkYearN,SliceLen,QStatistic,MissAccept,OpTim,Vectorised) end if do XYear = 1, WorkYearN TimLoaded (XTimFree,XReg,XYear) = Vectorised (XYear) end do end do if (EnsRegSame.EQ.1) then RegSame (XTimFree) = 1 else RegSame (XTimFree) = 0 end if YearSame (XTimFree) = 0 print*, " > Have sliced ensemble into: ", XTimFree if (XTimFree.EQ.WorkTimN) AllColUsed = 1 if (XTimFree.LT.WorkTimN) XTimFree = XTimFree + 1 deallocate (OpTim,Vectorised,YearVec, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SlicePerEns: Deallocation failure #####" end subroutine SlicePerEns !******************************************************************************* subroutine GaussSmoothA print*, " > Enter the time period (years) to smooth:" do read (*,*,iostat=ReadStatus), SliceLen if (ReadStatus.LE.0.AND.SliceLen.GE.2.AND.SliceLen.LT.(WorkYearN/2)) exit end do print*, " > Reinstate missing values? (1=no, 2=yes)" do read (*,*,iostat=ReadStatus), QKeepMiss if (ReadStatus.LE.0.AND.QKeepMiss.GE.1.AND.QKeepMiss.LE.2) exit end do allocate (Vectorised (WorkYearN), & HiPass (WorkYearN), & LoPass (WorkYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GaussSmoothA: Allocation failure #####" do XReg = 1, WorkRegN do XYear = 1, WorkYearN Vectorised (XYear) = TimLoaded (UseTim(1),XReg,XYear) end do call GaussSmooth (WorkYearN,SliceLen,QKeepMiss,Vectorised,LoPass,HiPass) do XYear = 1, WorkYearN TimLoaded (XTimFree,XReg,XYear) = LoPass (XYear) end do end do call AlertMiss deallocate (Vectorised, HiPass, LoPass, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: GaussSmoothA: Deallocation failure #####" end subroutine GaussSmoothA !******************************************************************************* subroutine AnomAPerA print*, " > Enter the first, last years of base period:" do read (*,*,iostat=ReadStatus), Year0, Year1 if (ReadStatus.LE.0.AND.Year0.GE.1.AND.Year1.GE.Year0.AND.Year1.LE.WorkYearN) exit end do PerLen = Year1 - Year0 + 1 print*, " > Calculate absolute (=1) or percentage (=2) anomalies ?" do read (*,*,iostat=ReadStatus), QAnom if (ReadStatus.LE.0.AND.QAnom.GE.1.AND.QAnom.LE.2) exit end do allocate (Vectorised(PerLen), & Bases(WorkRegN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AnomAPerA: Allocation failure #####" do XReg = 1, WorkRegN ! calc bases do XYear = 1, PerLen Vectorised(XYear) = TimLoaded(UseTim(1),XReg,(Year0+XYear-1)) end do Bases(XReg) = OpCalcMean (Vectorised, PerLen, MissAccept) end do if (QAnom.EQ.1) then do XReg = 1, WorkRegN ! calc abs anomalies do XYear = 1, WorkYearN if (TimLoaded(UseTim(1),XReg,XYear).NE.MissVal.AND.Bases(XReg).NE.MissVal) & TimLoaded(XTimFree,XReg,XYear) = TimLoaded(UseTim(1),XReg,XYear) - Bases(XReg) end do end do else ! calc % anomalies do XReg = 1, WorkRegN do XYear = 1, WorkYearN if (TimLoaded(UseTim(1),XReg,XYear).NE.MissVal.AND.Bases(XReg).NE.MissVal.AND.Bases(XReg).NE.0) & TimLoaded(XTimFree,XReg,XYear) = 100.0 * (TimLoaded(UseTim(1),XReg,XYear) - Bases(XReg)) / Bases(XReg) end do end do end if deallocate (Vectorised,Bases,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: AnomAPerA: Deallocation failure #####" call AlertMiss end subroutine AnomAPerA !******************************************************************************* end program SeqTim