! countries.f90 ! module for using the master countries file: master-cty.txt ! contains: ! ClarifyCty: for a vector of fresh stn, check the cty names ! requires: ! GridOps, SortMod, CtyFiles (from 23.1.04) module Countries use GridOps use SortMod use CtyFiles implicit none contains !******************************************************************************* ! Raw (required) are the vectors describing the fresh data-set (assumes caps and no hyphens) ! Ref (required) are the vectors describing a recent (not necessarily the most recent) ! version of the master code file [future mod could make this optional and load in sub] ! Got (required) returns the correct start/end codes, and continent code ! the correct country Cty is placed in RawCty subroutine ClarifyCty (RawCty,RawName,RawLat,RawLon,RawCode,RefCty,RefName,RefLat,RefLon, & GotCode0,GotCode1,GotContinent) real, dimension (:), pointer :: RawLat,RawLon,RefLat,RefLon,Distances integer, dimension (:), pointer :: GotCode0,GotCode1,GotContinent,RawCode integer, dimension (:), pointer :: MasterCode0,MasterCode1,MasterContinent integer, dimension (:), pointer :: Order character (len=20), dimension (:), pointer :: RawName,RefName,GotName character (len=13), dimension (:), pointer :: RawCty,RefCty,GotCty character (len=13), dimension (:), pointer :: MasterRawCty,MasterFinalCty integer, parameter :: MissVal = -999 character (len=13), parameter :: MissText = 'unknown' character (len=80), parameter :: MasterFile = './../../../data/cruts/cty/master.txt' real :: MinDistance integer :: AllocStat,ReadStatus,QChoice,QAddMaster,QLabel integer :: NRaw,NRef,NGot,NMaster,NMiss integer :: XRaw,XRef,XGot,XMaster,XMiss integer :: Cty1,Cty2,Cty3 character (len=13) :: CtyLabel,String13 !*************************************** preliminaries ! see routine below NRaw = size(RawCty) ; NGot = NRaw NRef = size(RefCty) if (NRaw.NE.size(RawLat).OR.NRaw.NE.size(RawLon).OR. & NRef.NE.size(RefLat).OR.NRef.NE.size(RefLon)) & print*, " > @@@@@ ERROR: vector size mismatched @@@@@" allocate (GotCty (NGot), & GotCode0 (NGot), & GotCode1 (NGot), & GotContinent (NGot), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ClarifyCty: Allocation failure: Got #####" GotCty = MissText NMaster=MasterSize() allocate (MasterRawCty (NMaster), & MasterFinalCty (NMaster), & MasterCode0 (NMaster), & MasterCode1 (NMaster), & MasterContinent (NMaster), & Distances (NRef), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ClarifyCty: Allocation failure #####" call LoadMasterCty (MasterRawCty,MasterFinalCty,MasterCode0,MasterCode1,MasterContinent) !*************************************** main do XRaw = 1, NRaw XMaster = 0 ! look for perfect match do XMaster = XMaster + 1 ! print "(4i8)", XRaw,XMaster,size(RawCty),size(MasterRawCty) ! @@@@@@@@@@@@@@@@@@@@@@@@ ! for some unknown reason, the program may think ! that MasterRawCty in the line below is unalloc unless ! the -g option is invoked on the pgf90 compiler ! if unalloc, -Mbounds will precipitate execution failure if (MasterRawCty(XMaster).EQ.RawCty(XRaw)) then GotCty(XRaw) = MasterFinalCty(XMaster) GotCode0(XRaw) = MasterCode0(XMaster) GotCode1(XRaw) = MasterCode1(XMaster) GotContinent(XRaw) = MasterContinent(XMaster) end if if (XMaster.EQ.NMaster.OR.RawCty(XRaw).EQ.MasterRawCty(XMaster)) exit end do if (GotCty(XRaw).EQ.MissText) then ! if no match yet found if (RawLat(XRaw).NE.MissVal.AND.RawLon(XRaw).NE.MissVal) then Distances = 10000000.0 ; MinDistance = 10000000.0 do XRef = 1, NRef ! get distances from ref stns if (RefLat(XRef).NE.MissVal.AND.RefLon(XRef).NE.MissVal) then Distances(XRef) = GetDistance(RawLat(XRaw),RawLon(XRaw),RefLat(XRef),RefLon(XRef)) if (Distances(XRef).LT.MinDistance) MinDistance = Distances(XRef) if (Distances(XRef).GT.(MinDistance+1000)) Distances(XRef) = MissVal end if end do allocate (Order(NRef), stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ClarifyCty: Allocation failure: Order #####" call QuickSort (Reals=Distances,OrderValid=Order,NMiss=NMiss) ! find closest stns XRef = 0 do ! look for matching stn in master data-set XRef=XRef+1 if (Distances(Order(XRef)).EQ.0.OR.trim(RawName(XRaw)).EQ. & trim(RefName(Order(XRef)))) then RawCty(XRaw) = RefCty(Order(XRef)) XMaster = 0 ! find the match in master do XMaster = XMaster + 1 if (RawCty(XRaw).EQ.MasterRawCty(XMaster)) then GotCty(XRaw) = MasterFinalCty(XMaster) GotCode0(XRaw) = MasterCode0(XMaster) GotCode1(XRaw) = MasterCode1(XMaster) GotContinent(XRaw) = MasterContinent(XMaster) end if if (XMaster.EQ.NMaster.OR.RawCty(XRaw).EQ.MasterRawCty(XMaster)) exit end do end if if (Distances(Order(XRef)).GE.8.OR.RawCty(XRaw).EQ.RefCty(Order(XRef))) exit end do end if end if if (GotCty(XRaw).EQ.MissText) then ! do specific matches for naughty abbrevs if (trim(RawCty(XRaw)).EQ.'CHI' & .AND.RawCode(XRaw).GE.5000000.AND.RawCode(XRaw).LE.5999999) then GotCty(XRaw) = "CHINA" else if (trim(RawCty(XRaw)).EQ.'CHI' & .AND.RawCode(XRaw).GE.8540000.AND.RawCode(XRaw).LE.8599999) then GotCty(XRaw) = "CHILE" else if (trim(RawCty(XRaw)).EQ.'IND' & .AND.RawCode(XRaw).GE.4200000.AND.RawCode(XRaw).LE.4339999) then GotCty(XRaw) = "INDIA" else if (trim(RawCty(XRaw)).EQ.'IND' & .AND.RawCode(XRaw).GE.9600000.AND.RawCode(XRaw).LE.9799999) then GotCty(XRaw) = "INDONESIA" else if (trim(RawCty(XRaw)).EQ.'AUS' & .AND.RawCode(XRaw).GE.9410000.AND.RawCode(XRaw).LE.9599999) then GotCty(XRaw) = "AUSTRALIA" else if (trim(RawCty(XRaw)).EQ.'AUS' & .AND.RawCode(XRaw).GE. 110000.AND.RawCode(XRaw).LE. 113999) then GotCty(XRaw) = "AUSTRIA" else if (trim(RawCty(XRaw)).EQ.'CAN' & .AND.RawCode(XRaw).GE.7100000.AND.RawCode(XRaw).LE.7199999) then GotCty(XRaw) = "CANADA" end if if (GotCty(XRaw).NE.MissText) then XMaster = 0 do XMaster = XMaster + 1 if (GotCty(XRaw).EQ.MasterRawCty(XMaster)) then GotCode0(XRaw) = MasterCode0(XMaster) GotCode1(XRaw) = MasterCode1(XMaster) GotContinent(XRaw) = MasterContinent(XMaster) end if if (GotCty(XRaw).EQ.MasterRawCty(XMaster)) exit end do end if end if if (GotCty(XRaw).EQ.MissText) then ! if no match yet found if (RawLat(XRaw).NE.MissVal.AND.RawLon(XRaw).NE.MissVal) then ! find 1st closest cty Cty1 = Order(1) ; XRef = 1 ; Cty2 = Cty1 ; Cty3 = Cty1 do ! find 2nd closest cty XRef = XRef + 1 if (RefCty(Order(XRef)).NE.RefCty(Cty1)) Cty2 = Order(XRef) if (Cty2.NE.Cty1.OR.XRef.EQ.(NRef-NMiss)) exit end do do ! find 3rd closest cty XRef = XRef + 1 if (RefCty(Order(XRef)).NE.RefCty(Cty1).AND.RefCty(Order(XRef)).NE.RefCty(Cty2)) & Cty3 = Order(XRef) if (Cty3.NE.Cty1.OR.XRef.EQ.(NRef-NMiss)) exit end do deallocate (Order, stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ClarifyCty: Deallocation failure: Order #####" print "(3a,i8,a)", " > '", trim(RawCty(XRaw)), "' (", RawCode(XRaw), & ") has no match. Select WMO range: manual (>0)," print "(7a)", " > ", trim(RefCty(Cty1)), " (-1), ", trim(RefCty(Cty2)), " (-2), ", & trim(RefCty(Cty3)), " (-3)" do ! choose which WMO code range to adopt read (*,*,iostat=ReadStatus), QChoice if (ReadStatus.LE.0.AND.QChoice.GE.-3.AND.QChoice.LE.NMaster) exit end do if (QChoice.LT.0) then if (abs(QChoice).EQ.1) XRef = Cty1 if (abs(QChoice).EQ.2) XRef = Cty2 if (abs(QChoice).EQ.3) XRef = Cty3 XMaster = 0 ! find the chosen master cty entry do XMaster = XMaster + 1 if (MasterFinalCty(XMaster).EQ.RefCty(XRef)) exit end do else XMaster = QChoice end if else ! if no lat/lon check possible print "(3a,i8,a)", " > '", trim(RawCty(XRaw)), "' (", RawCode(XRaw), & ") has no match. Select WMO range: manual (>0)." do ! choose which WMO code range to adopt read (*,*,iostat=ReadStatus), XMaster if (ReadStatus.LE.0.AND.XMaster.GE.(0-NMaster).AND.XMaster.LE.NMaster) exit end do end if if (trim(RawCty(XRaw)).EQ.'UNKNOWN') then QLabel = 1 else print "(5a)", " > Select cty label: ", trim(MasterFinalCty(XMaster)), & " (=1), ", trim(RawCty(XRaw)), " (=2), manual (=3), permanent (<0)" do ! choose which cty to adopt read (*,*,iostat=ReadStatus), QLabel if (QLabel.EQ.2) print*, " > Permanent entry must be made. " if (QLabel.EQ.3) print*, " > Permanent entry must be made. " if (ReadStatus.LE.0.AND.QLabel.GE.-3.AND.QLabel.LE.1) exit end do end if if (abs(QLabel).EQ.1) then GotCty(XRaw) = MasterFinalCty(XMaster) else if (abs(QLabel).EQ.2) then GotCty(XRaw) = RawCty(XRaw) else if (abs(QLabel).EQ.3) then do ! choose which cty to adopt print*, " > Enter the cty label (max 13 char): " read (*,*,iostat=ReadStatus), CtyLabel if (ReadStatus.LE.0.AND.CtyLabel.NE."") exit end do GotCty(XRaw) = CtyLabel end if GotCode0(XRaw) = MasterCode0(XMaster) GotCode1(XRaw) = MasterCode1(XMaster) GotContinent(XRaw) = MasterContinent(XMaster) if (QLabel.LT.0) then ! unload old cty master data ! print*, " > Deallocating..." ! @@@@@@@@@@@@@@@@@ deallocate (MasterRawCty,MasterFinalCty,MasterCode0,MasterCode1,MasterContinent,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ClarifyCty: Deallocation failure #####" ! add new country entry ! print*, " > Appending to ", trim(MasterFile) ! @@@@@@@@@@@@@@@@@ open (3,file=MasterFile,status="old",position="append",action="write") write (3,"(2(a13,x),x,3(x,i9))"), RawCty(XRaw),GotCty(XRaw),GotCode0(XRaw),GotCode1(XRaw),& GotContinent(XRaw) close (3) ! sort updated master file call system ('sort -o ' // trim(MasterFile) // ' ' // trim(MasterFile)) call LoadMasterCty (MasterRawCty,MasterFinalCty,MasterCode0,MasterCode1,MasterContinent) NMaster = size(MasterRawCty) ! reload updated cty master data ! print*, " > Reloading with cty total ", NMaster ! @@@@@@@@@@@@@@@@@ end if end if RawCty(XRaw) = GotCty(XRaw) end do !*************************************** exit deallocate (MasterRawCty,MasterFinalCty,MasterCode0,MasterCode1,MasterContinent, & GotCty,Distances,stat=AllocStat) if (AllocStat.NE.0) print*, " > ##### ERROR: ClarifyCty: Deallocation failure #####" end subroutine ClarifyCty !******************************************************************************* end module Countries