! scalemod.f90 ! module procedure written by Tim Mitchell in Jan 2000 ! last modification on 10.02.00 ! includes all the routines necessary to run a scaling operation ! PredictRun, PredictError, PredictErrorStat module ScaleMod implicit none contains !******************************************************************************* subroutine PredictRun (JobMemN,JobYearN,ActualExe,PredictWye,Aye) real, dimension (:,:), pointer :: ActualExe, PredictWye real, intent (in) :: Aye integer, intent (in) :: JobMemN, JobYearN real, parameter :: MissVal = -999.0 integer :: XYear, XMem do XMem = 1, JobMemN do XYear = 1, JobYearN if (ActualExe(XMem,XYear).NE.MissVal) then PredictWye(XMem,XYear) = Aye * ActualExe(XMem,XYear) end if end do end do end subroutine PredictRun !******************************************************************************* subroutine PredictError (MissAccept,RefMethod,JobMemN,JobYearN,SliceLen,ActualWye,PredictWye,& ErrorMSE,ReferenceMSE,FractionMSE) real, dimension (:,:), pointer :: ActualWye, PredictWye real, dimension (:) , pointer :: ErrorMSE, ReferenceMSE, FractionMSE real, intent (in) :: MissAccept integer, intent (in) :: JobMemN, JobYearN, SliceLen integer, intent (in) :: RefMethod ! 1=internal-var 2=controlzero 3=Brier real, dimension (:,:), allocatable :: ActualMean, PredictMean integer, dimension (:,:), allocatable :: YearCheck integer, dimension (:), allocatable :: MemCheck real, parameter :: MissVal = -999.0 real :: ActualTot, PredictTot, DiffSqTot, ValidEn integer :: XMem, XMem0, XMem1, XYear, XPredict, XActual integer :: SliceMidYear, SliceStartYear, SliceEndYear integer :: Threshold integer :: TotalMiss, TotalValid integer :: AllocStat !*************************************** ErrorMSE = MissVal ReferenceMSE = MissVal FractionMSE = MissVal allocate (ActualMean (JobMemN,JobYearN), & PredictMean(JobMemN,JobYearN), & YearCheck (JobMemN,JobYearN), & MemCheck (JobYearN), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: Allocation failure #####" ActualMean = MissVal PredictMean = MissVal YearCheck = 0 MemCheck = 0 Threshold = nint (MissAccept * real(SliceLen)/ 100.0) !*************************************** do XMem = 1, JobMemN do SliceStartYear = 1, (JobYearN-SliceLen+1) SliceMidYear = SliceStartYear + floor(real(SliceLen)/2.0) TotalMiss = 0 ValidEn = 0.0 ActualTot = 0.0 PredictTot = 0.0 do XYear = SliceStartYear, (SliceStartYear+SliceLen-1) if (ActualWye(XMem,XYear).EQ.MissVal.OR.PredictWye(XMem,XYear).EQ.MissVal) then TotalMiss = TotalMiss + 1 else ActualTot = ActualTot + ActualWye(XMem,XYear) PredictTot = PredictTot + PredictWye(XMem,XYear) ValidEn = ValidEn + 1.0 end if end do if (TotalMiss.LE.Threshold.AND.ValidEn.GE.1) then ! checks that no. of valid values in slice >= 90% YearCheck (XMem,SliceMidYear) = 1 ActualMean (XMem,SliceMidYear) = ActualTot / ValidEn PredictMean (XMem,SliceMidYear) = PredictTot / ValidEn end if end do end do !*************************************** do SliceStartYear = 1, (JobYearN-SliceLen+1) SliceMidYear = SliceStartYear + floor(real(SliceLen)/2.0) TotalValid = 0 do XMem = 1, JobMemN if (YearCheck(XMem,SliceMidYear).EQ.1) TotalValid = TotalValid + 1 end do if (TotalValid.GT.1) MemCheck (SliceMidYear) = 1 end do !*************************************** do SliceStartYear = 1, (JobYearN-SliceLen+1) SliceMidYear = SliceStartYear + floor(real(SliceLen)/2.0) if (MemCheck(SliceMidYear).EQ.1) then ! if sufficient members for a calc DiffSqTot = 0.0 ValidEn = 0.0 do XPredict = 1, JobMemN ! error do XActual = 1, JobMemN if (YearCheck(XMem,SliceMidYear).EQ.1) then if (PredictMean(XPredict,SliceMidYear).NE.MissVal.AND.ActualMean(XActual,SliceMidYear).NE.MissVal) then DiffSqTot = DiffSqTot + (PredictMean(XPredict,SliceMidYear) - ActualMean(XActual,SliceMidYear)) ** 2 ValidEn = ValidEn + 1.0 end if end if end do end do if (ValidEn.GT.1) ErrorMSE (SliceMidYear) = DiffSqTot / ValidEn if (RefMethod.EQ.1) then ! internal var = reference DiffSqTot = 0.0 ValidEn = 0.0 do XPredict = 1, JobMemN do XActual = 1, JobMemN if (YearCheck(XMem,SliceMidYear).EQ.1) then if (ActualMean(XActual,SliceMidYear).NE.MissVal) then DiffSqTot = DiffSqTot + (ActualMean(XPredict,SliceMidYear) - ActualMean(XActual,SliceMidYear)) ** 2 ValidEn = ValidEn + 1.0 end if end if end do end do if (ValidEn.GT.JobMemN) ReferenceMSE (SliceMidYear) = DiffSqTot / ValidEn else if (RefMethod.EQ.2.OR.RefMethod.EQ.3) then ! control of pred=0 = reference DiffSqTot = 0.0 ValidEn = 0.0 do XActual = 1, JobMemN if (YearCheck(XMem,SliceMidYear).EQ.1) then if (ActualMean(XActual,SliceMidYear).NE.MissVal) then DiffSqTot = DiffSqTot + (ActualMean(XActual,SliceMidYear)) ** 2 ValidEn = ValidEn + 1.0 end if end if end do if (ValidEn.GT.1) ReferenceMSE (SliceMidYear) = DiffSqTot / ValidEn end if ! calc of fraction if (ReferenceMSE(SliceMidYear).NE.MissVal.AND.ErrorMSE(SliceMidYear).NE.MissVal) then if (ReferenceMSE(SliceMidYear).NE.0) then if (RefMethod.EQ.1.OR.RefMethod.EQ.2) then FractionMSE (SliceMidYear) = ErrorMSE (SliceMidYear) / ReferenceMSE (SliceMidYear) else if (RefMethod.EQ.3) then FractionMSE (SliceMidYear) = 1 - (ErrorMSE (SliceMidYear) / ReferenceMSE (SliceMidYear)) end if end if end if end if end do !*************************************** deallocate (ActualMean,PredictMean,YearCheck,MemCheck) end subroutine PredictError !******************************************************************************* subroutine SetUpErrorStat (MissAccept,JobADYear,JobYearN,SliceLen,QMethod,FoundYear0,FoundYear1,& StatThreshold,MissThreshold) integer, dimension (:), pointer :: JobADYear real, intent (in) :: MissAccept real, intent (out) :: StatThreshold integer, intent (in) :: JobYearN, SliceLen integer, intent (out) :: FoundYear0,FoundYear1,MissThreshold integer, intent (out) :: QMethod ! 1=%>threshold 2=mean-over-period real, parameter :: MissVal = -999.0 integer :: LowerTrim, UpperTrim ! allowances in MissThreshold due to trimming from SliceLen>1 integer :: ReadStatus integer :: GetYear0,GetYear1 integer :: XYear !*************************************** ! make selections !print*, " > Select the prediction error statistic to calculate: " !print*, " > 1. % of chosen period that Error/Internal < chosen threshold" !print*, " > 2. mean of Error/Internal over chosen period" !do ! read (*,*,iostat=ReadStatus), QMethod ! if (ReadStatus.LE.0.AND.QMethod.GE.1.AND.QMethod.LE.2) exit !end do QMethod = 2 print*, " > Select first and last years AD of period: " do read (*,*,iostat=ReadStatus), GetYear0, GetYear1 if (ReadStatus.LE.0.AND.GetYear1.GE.GetYear0) exit end do if (QMethod.EQ.1) then print*, " > Select the Error/Internal threshold : " do read (*,*,iostat=ReadStatus), StatThreshold if (ReadStatus.LE.0) exit end do else StatThreshold = MissVal end if !*************************************** ! locate years AD XYear = 0 FoundYear0 = 0 do XYear = XYear + 1 if (JobADYear(XYear).EQ.GetYear0) FoundYear0 = XYear if (FoundYear0.GT.0) exit if (XYear.EQ.JobYearN) exit end do if (FoundYear0.EQ.0) print*, " > ##### ERROR: Initial year selected not found #####" FoundYear1 = FoundYear0 + GetYear1 - GetYear0 UpperTrim = max ((FoundYear1-(JobYearN-floor(real(SliceLen/2.0)))),0) LowerTrim = max ((floor(real(SliceLen/2.0))-FoundYear0),0) MissThreshold = nint (MissAccept * (real(FoundYear1 - FoundYear0 + 1) / 100.0)+UpperTrim+LowerTrim) end subroutine SetUpErrorStat !******************************************************************************* subroutine PredictErrorStat (AllFractionMSE,JobADYear,RegN,JobYearN,QMethod,FoundYear0,FoundYear1,& StatThreshold,MissThreshold,AllErrorStat) real, dimension (:,:), pointer :: AllFractionMSE real, dimension (:), pointer :: AllErrorStat integer, dimension (:), pointer :: JobADYear real, intent (in) :: StatThreshold integer, intent (in) :: RegN, JobYearN, QMethod, FoundYear0, FoundYear1, MissThreshold real, parameter :: MissVal = -999.0 real :: PerEn, PerTot integer :: XYear, XReg integer :: ReadStatus integer :: PerMiss !*************************************** ! method 1 if (QMethod.EQ.1) then do XReg = 1, RegN PerTot = 0.0 PerEn = 0.0 PerMiss = 0 do XYear = FoundYear0, FoundYear1 if (AllFractionMSE(XReg,XYear).NE.MissVal) then PerEn = PerEn + 1.0 if (AllFractionMSE(XReg,XYear).LT.StatThreshold) & PerTot = PerTot + 1.0 else PerMiss = PerMiss + 1 end if end do if (PerMiss.LE.MissThreshold) then AllErrorStat (XReg) = 100.0 * (PerTot / PerEn) else AllErrorStat (XReg) = MissVal end if end do end if !*************************************** ! method 2 if (QMethod.EQ.2) then do XReg = 1, RegN PerTot = 0.0 PerEn = 0.0 PerMiss = 0 do XYear = FoundYear0, FoundYear1 if (AllFractionMSE(XReg,XYear).NE.MissVal) then PerTot = PerTot + AllFractionMSE(XReg,XYear) PerEn = PerEn + 1.0 else PerMiss = PerMiss + 1 end if end do if (PerMiss.LE.MissThreshold) then AllErrorStat (XReg) = PerTot / PerEn else AllErrorStat (XReg) = MissVal end if end do end if end subroutine PredictErrorStat !******************************************************************************* end module ScaleMod