! perfiles.f90 ! module in which all save to .per file routines are held ! contains: SavePER, etc ! the power of SavePerSilent is now available through options on SavePer module SavePerFiles use FileNames implicit none contains !******************************************************************************* ! save .per files ! call with AllData, or with Monthly+Seasonal+Annual subroutine SavePer (CallFile, YearAD, CallVariCode, AllData, & Monthly, Seasonal, Annual, CallLineFormat, NoResponse, & ExtraHeads,ScenHeads,CallPoliUnitName,CallVariableName) real, pointer,dimension (:,:),optional :: Monthly, Seasonal,AllData real, pointer,dimension (:), optional :: Annual integer, pointer, dimension (:) :: YearAD character (len=20), intent(in),optional :: CallLineFormat ! specify if you don't want the auto hi-prec character (len=20), intent(in),optional :: CallPoliUnitName ! reg-name character (len=80), intent(in),optional :: CallVariableName ! variable character (len=80), intent(in) :: CallFile ! can be blank character(len=158),pointer,dimension(:) :: Headers integer, intent(in) :: CallVariCode ! can be MissVal, -1=min,0=mean,1=max,2=sum integer, intent(in), optional :: NoResponse ! ensures no run-time inputs are required integer, intent(in), optional :: ExtraHeads ! writes extra header lines if =1 integer, intent(in), optional :: ScenHeads ! writes scen header lines if =1 real, parameter :: MissVal = -999.0 integer :: NoSave, ReadStatus, AllocStat integer :: YearN, MonthN, SeasonN, HeaderN integer :: XYear, XMonth, XSeason, XHeader, XPeriod integer :: VariCode, QSepAll character (len=80) :: SaveFile, NameVa character (len=20) :: LineFormat, NamePU character (len= 4) :: Suffix !*************************************** ! check sizes NoSave = 0 Suffix = ".per" if (present(Monthly).AND.present(Seasonal).AND.present(Annual)) then YearN = size (Monthly,1) MonthN = size (Monthly,2) SeasonN = size (Seasonal,2) if (size(YearAD).NE.YearN.OR.size(Seasonal,1).NE.YearN.OR.size(Annual).NE.YearN & .OR.MonthN.NE.12.OR.SeasonN.NE.4) then print*, " > SavePER: No save. Weird number of months or years." NoSave = 1 else QSepAll = 1 end if else if (present(AllData)) then YearN = size (AllData,1) if (size(AllData,2).NE.17) then print*, " > SavePER: No save. Weird number of seasons." NoSave = 1 else QSepAll = 2 end if else print*, " > ##### ERROR : SavePer: No input data specified #####" end if if (CallVariCode.LT.-1.OR.CallVariCode.GT.2) then if (present(NoResponse)) then print*, " > ##### SavePER: No save. Clash between spec and data needs. #####" NoSave = 1 else 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 else VariCode = CallVariCode end if if (present(CallLineFormat)) then LineFormat = trim(adjustl(CallLineFormat)) else if (present(NoResponse)) then LineFormat = '(i5,12f9.3,5f9.3)' else call MakePERLineFormat (LineFormat) end if end if if (present(ExtraHeads)) then HeaderN=20 else if (present(ScenHeads)) then HeaderN=15 else HeaderN= 4 end if allocate (Headers(HeaderN),stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SavePER: allocation failure #####" if (present(ExtraHeads).OR.present(ScenHeads)) then if (present(CallPoliUnitName)) then NamePU = CallPoliUnitName else NamePU = " " end if if (present(CallVariableName)) then NameVa = CallVariableName else NameVa = " " end if if (present(ExtraHeads)) then call MakePERHeaders (VariCode,LineFormat,YearAD,Headers,& ManyHeads=ExtraHeads,PoliUnitName=NamePU,VariableName=NameVa) else call MakePERHeaders (VariCode,LineFormat,YearAD,Headers,& ScenHeads=ScenHeads, PoliUnitName=NamePU,VariableName=NameVa) end if else call MakePERHeaders (VariCode,LineFormat,YearAD,Headers) end if !*************************************** ! save data to file if (NoSave.EQ.0) then SaveFile = SavePath (CallFile,Suffix) open (2, file=SaveFile, status="replace", access="sequential", form="formatted", action="write") do XHeader = 1, HeaderN write (2,"(a158)"), Headers(XHeader) end do do XYear = 1, YearN if (QSepAll.EQ.1) write (2,LineFormat), YearAD(XYear), (Monthly(XYear,XMonth), XMonth=1,12), & (Seasonal(XYear,XSeason), XSeason=1,4), Annual(XYear) if (QSepAll.EQ.2) write (2,LineFormat), YearAD(XYear), (AllData(XYear,XPeriod), XPeriod=1,17) end do close (2) end if deallocate (Headers,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: SavePER: Deallocation failure #####" end subroutine SavePer !******************************************************************************* ! make line format for save to .per subroutine MakePerLineFormat (LineFormat) character (len=20), intent(out) :: LineFormat integer :: ReadStatus character (len=1) :: DeciTxtShort LineFormat = "" print*, " > Enter the no. of decimal places to save (1...3): " print*, " > ...for MONTHS: " do read (*,*,iostat=ReadStatus), DeciTxtShort if (ReadStatus.GT.0) print*, " > Not a string. Try again." if (DeciTxtShort.EQ."") print*, " > A null string. Try again." if (ReadStatus.LE.0.AND.DeciTxtShort.NE."") exit end do LineFormat = '(i5,12f9.' // DeciTxtShort // ',5f9.' print*, " > ...for SEASONS,ANNUALS: " do read (*,*,iostat=ReadStatus), DeciTxtShort if (ReadStatus.GT.0) print*, " > Not a string. Try again." if (DeciTxtShort.EQ."") print*, " > A null string. Try again." if (ReadStatus.LE.0.AND.DeciTxtShort.NE."") exit end do LineFormat = LineFormat(1:15) // DeciTxtShort // ')' end subroutine MakePerLineFormat !******************************************************************************* ! make headers for .per data files subroutine MakePerHeaders (VariCode,LineFormat,YearAD,Headers, & ManyHeads,ScenHeads,PoliUnitName,VariableName) integer, dimension (:), pointer :: YearAD character (len=158), pointer, dimension (:) :: Headers integer, intent (in), optional :: ManyHeads ! writes extra headers if =1 integer, intent (in), optional :: ScenHeads ! writes scen headers if =1 integer, intent (in) :: VariCode ! -1=min, 0=mean, 1=max, 2=sum character (len=20),intent(in) :: LineFormat character (len=20),intent(in), optional :: PoliUnitName character (len=80),intent(in), optional :: VariableName real, parameter :: MissVal = -999.0 integer :: AllocStat integer :: YearN,HeaderN character (len=12) :: Date, Time character (len=8) :: TimePeriod, Variable character (len=4 ) :: Year, Year0, Year1 character (len=2 ) :: Month, Day, Hour, Minute !*************************************** TimePeriod= "Periodic" ; Variable = "" ; Year0 = "" YearN = size (YearAD) ; HeaderN=size(Headers) if (VariCode.EQ.-1) Variable = "Min" if (VariCode.EQ. 0) Variable = "Mean" if (VariCode.EQ. 1) Variable = "Max" if (VariCode.EQ. 2) Variable = "Sum" if (YearAD(1).GT.0.AND.YearAD(YearN).GE.YearAD(1)) then open (1,status="scratch") write (1,"(2i4)"), YearAD(1), YearAD(YearN) rewind (1) read (1,"(2a4)"), Year0, Year1 close (1) else print*, " > ##### ERROR: MakePerHeaders: weird period #####" end if call date_and_time (Date, Time) Year = Date (1:4) ; Month = Date (5:6) ; Day = Date (7:8) Hour = Time (1:2) ; Minute= Time (3:4) if (present(ManyHeads)) then if (ManyHeads.EQ.1) then Headers = " " Headers ( 1) = "Monthly, seasonal, and annual climate observations averaged for political units." if (present(PoliUnitName)) Headers ( 2) = "Political unit = " // trim(adjustl(PoliUnitName)) if (present(VariableName)) Headers ( 3) = "Variable = " // trim(adjustl(VariableName)) Headers ( 4) = "Period = " // Year0 // "-" // Year1 // ": missing value = -999.0 : format = " // & trim(adjustl(LineFormat)) Headers ( 5) = "*" Headers ( 6) = "File created and owned by Dr. Tim Mitchell (t.mitchell@uea.ac.uk). Full rights retained." Headers ( 7) = "Created at the Tyndall Centre (www.tyndall.ac.uk) on " & // Day // "." // Month // "." // Year // " at " // Hour // ":" // Minute Headers ( 8) = "The data in this file may be used for non-commercial scientific and educational purposes." Headers ( 9) = "Where research using this data is published, the source should be acknowledged as: " Headers (10) = " Mitchell,T.D. et al 2003: A comprehensive set of climate scenarios for Europe" Headers (11) = " and the globe. In prep." Headers (12) = "Method: The country aggregation is based on the CRU TS 2.0 gridded data-set." Headers (13) = " The gridded data were aggregated into countries using political boundaries; see:" Headers (14) = " Mitchell,Hulme,New,2001: Climate data for political areas. Area 34:109-112" Headers (15) = "For more information see http://www.cru.uea.ac.uk/~timm/" Headers (16) = "Disclaimer: No responsibility is taken for the accuracy of these data." Headers (17) = "Disclaimer: No political statement is implied in the selection of these political units." Headers (18) = "*" Headers (19) = "*" if (LineFormat(8:8).EQ.'8') then Headers (20) = ' YEAR JAN FEB MAR APR MAY JUN JUL ' // & 'AUG SEP OCT NOV DEC MAM JJA SON DJF ANN' else Headers (20) = ' YEAR JAN FEB MAR APR MAY JUN JUL ' // & 'AUG SEP OCT NOV DEC MAM JJA SON DJF ANN' end if end if else if (present(ScenHeads)) then Headers = "*" Headers (1) = "A Tyndall Centre file (www.tyndall.ac.uk) created on " & // Day // "." // Month // "." // Year // " at " // Hour // ":" // Minute & // " by Dr. Tim Mitchell" Headers (2) = "Scenario .per data; time,var codes: " // TimePeriod // " " // Variable Headers (3) = "Scenarios" // Year0 // "-" // Year1 // ": missing value = -999.0 : format = " // LineFormat Headers (5) = "This is part of the TYN CY 3.0 data-set. See http://www.cru.uea.ac.uk/~timm/" if (present(PoliUnitName)) Headers ( 6) = "Political unit = " // trim(adjustl(PoliUnitName)) if (present(VariableName)) Headers ( 7) = "Variable = " // trim(adjustl(VariableName)) Headers (9) = "The scenario indices each represent a GCM/SRES combination:" Headers(10) = " CGCM2: 1=A1FI, 2=A2, 3=B2, 4=B1" Headers(11) = " CSIRO2: 5=A1FI, 6=A2, 7=B2, 8=B1" Headers(12) = " HadCM3: 9=A1FI,10=A2,11=B2,12=B1" Headers(13) = " PCM:13=A1FI,14=A2,15=B2,16=B1" if (LineFormat(8:8).EQ.'8') then Headers (15) = ' SCEN JAN FEB MAR APR MAY JUN JUL ' // & 'AUG SEP OCT NOV DEC MAM JJA SON DJF ANN' else Headers (15) = ' SCEN JAN FEB MAR APR MAY JUN JUL ' // & 'AUG SEP OCT NOV DEC MAM JJA SON DJF ANN' end if else Headers = "" Headers (1) = "Tyndall Centre file (www.tyndall.ac.uk) created on " & // Day // "." // Month // "." // Year // " at " // Hour // ":" // Minute & // " by Dr. Tim Mitchell" Headers (2) = "Periodic .per data; time,var codes: " // TimePeriod // " " // Variable Headers (3) = "Period = " // Year0 // "-" // Year1 // ": missing value = -999.0 : format = " // LineFormat if (LineFormat(8:8).EQ.'8') then Headers (4) = ' YEAR JAN FEB MAR APR MAY JUN JUL ' // & 'AUG SEP OCT NOV DEC MAM JJA SON DJF ANN' else Headers (4) = ' YEAR JAN FEB MAR APR MAY JUN JUL ' // & 'AUG SEP OCT NOV DEC MAM JJA SON DJF ANN' end if end if end subroutine MakePerHeaders !******************************************************************************* end module SavePerFiles