;************************************************************************* ; Note: several of the functions/procedures are used ; to invoke old [ugly!] function names. ;************************************************************************* ; D. Shea ; ; convert WRF character variable "Times" to udunits ; 2001-06-11_12:00:00 ; ; convert WRF character variable "Times" to a coordinate variable "Time" ; opt can be "integer" or "string" ; . integer: opt = 0 : hours since initial time: Times(0,:) ; . opt = 1 : hours since 1901-01-01 00:00:00 ; . string: opt = 'any udunits compatible string' ; undef ("WRF_Times2Udunits_c") function WRF_Times2Udunits_c(Times:character, opt) local dimT, rank, year, month, day, hour, minute, sec, units, time begin dimT = dimsizes(Times) rank = dimsizes(dimT) if (rank.ne.2) then print("===> WRF_contributed.ncl: WRF_Times2Udunits_c expects 2D array: rank="+rank) exit end if if (.not.(typeof(opt).eq."integer" .or. typeof(opt).eq."string")) then print("===> WRF_contributed.ncl: opt must be integer or string: type="+typeof(opt)) exit end if year = stringtointeger((/Times(:, 0:3) /)) month = stringtointeger((/Times(:, 5:6) /)) day = stringtointeger((/Times(:, 8:9) /)) hour = stringtointeger((/Times(:,11:12)/)) minute = stringtointeger((/Times(:,14:15)/)) sec = stringtointeger((/Times(:,17:18)/)) if (typeof(opt).eq."integer") then if (opt.eq.0) then units = "hours since "+year(0)+"-" \ +sprinti("%0.2i",month(0)) +"-" \ +sprinti("%0.2i",day(0)) +" " \ +sprinti("%0.2i",hour(0)) +":" \ +sprinti("%0.2i",minute(0))+":" \ +sprinti("%0.2i",sec(0)) else units = "hours since 1901-01-01 00:00:00" end if else units = opt ; opt is udunits compatible string end if Time = ut_inv_calendar(year,month,day,hour,minute,sec, units, 0) Time!0 = "Time" Time@long_name = "Time" Time@description= "Time" Time@units = units Time&Time = Time ; make coordinate variable return (Time) end ;************************************************************************* ; D. Shea ; interface to WRF_Times2Udunits_c undef ("WRF_Times_to_udunits") function WRF_Times_to_udunits(Times:character, opt) begin return( WRF_Times2Udunits_c(Times, 0) ) ; old name end ;************************************************************************* ; D. Shea ; convert WRF character variable "Times" to ; a coordinate variable of type double ; time(double) = yyyymmddhhmnss ; 2001-06-11_12:00:00 ==> 20010611120000 ; ; opt: currently not used [dummy] ; undef ("WRF_Times2double_c") function WRF_Times2double_c(Times:character, opt) local dimT, rank, N, time, i, tmp_c begin dimT = dimsizes(Times) rank = dimsizes(dimT) if (rank.ne.2) then print("===> WRF_contributed.ncl: WRF_Times2Udunits_c expects 2D array: rank="+rank) exit end if N = dimT(0) Time = new( N ,"double") ; preset to "double" delete(Time@_FillValue) ; coord variables should not have a _FillValue Time = stringtointeger((/Times(:,0:3)/)) *1d10 + \ ; yyyy stringtointeger((/Times(:,5:6)/)) *1d8 + \ ; mm stringtointeger((/Times(:,8:9)/)) *1d6 + \ ; dd stringtointeger((/Times(:,11:12)/))*1d4 + \ ; hh stringtointeger((/Times(:,14:15)/))*1d2 + \ ; mn stringtointeger((/Times(:,17:18)/))*1d0 ; ss Time!0 = "Time" Time@long_name = "Time" Time@description= "Time" Time@units = "yyyymmddhhmnss" Time&Time = Time ; make coordinate variable return (Time) end ;************************************************************************* ; D. Shea ; interface to WRF_Times2double_c ; more explicit function name undef ("WRF_Times_to_ymdhms") function WRF_Times_to_ymdhms(Times:character, opt) begin return( WRF_Times2double_c(Times, 0) ) ; old name end ;************************************************************************* ; D. Shea ; convert WRF character variable "Times" to ; a coordinate variable of type integer ; time(integer)= yyyymmddhh [->ymdh] ; 2001-06-11_12:00:00 ==> 2001061112 ; ; Note: mminute and second are not part of the returned time ; ; opt: currently not used [dummy] ; undef ("WRF_Times_to_ymdh") function WRF_Times_to_ymdh(Times:character, opt) local dimT, rank, N, time, i, tmp_c begin dimT = dimsizes(Times) rank = dimsizes(dimT) if (rank.ne.2) then print("===> WRF_contributed.ncl: WRF_Times2yyyymmddhh expects 2D array: rank="+rank) exit end if N = dimT(0) Time = new( N ,"integer") delete(Time@_FillValue) ; coord variables should not have a _FillValue Time = stringtointeger((/Times(:,0:3)/)) *1000000 + \ ; yyyy stringtointeger((/Times(:,5:6)/)) *10000 + \ ; mm stringtointeger((/Times(:,8:9)/)) *100 + \ ; dd stringtointeger((/Times(:,11:12)/)) ; hh Time!0 = "Time" Time@long_name = "Time" Time@description= "Time" Time@units = "yyyymmddhh" Time&Time = Time ; make coordinate variable return (Time) end ;************************************************************************* ; D. Shea ; This is a driver that selects the appropriate ; mapping function based upon the file attribute: MAP_PROJ ; MAP_PROJ=1 [Lambert Conformal]; =2 [Stereographic]; =3 [Mercator] ; ; opt: currently not used [potentail use: time counter for XLAT/XLONG] ; ; Sample usage: ; ncdf = addfile("...", r") ; res = True ; WRF_map_c (ncdf, res, 0) ; res = ... ; undef("WRF_map_c") procedure WRF_map_c (f:file, res:logical, opt) local rank, dimll, nlat, mlon, lat2d, lon2d begin if (isatt(f,"MAP_PROJ")) then if (f@MAP_PROJ.eq.1) then res@mpProjection = "LambertConformal" end if if (f@MAP_PROJ.eq.2) then res@mpProjection = "Stereographic" end if if (f@MAP_PROJ.eq.3) then res@mpProjection = "Mercator" end if else print ("WRF_mapProj: no MAP_PROJ attribute") end if rank = dimsizes(filevardimsizes(f,"XLAT")) ; # of dimensions if (rank.eq.3) then lat2d = f->XLAT(0,:,:) ; opt could bt "nt" f->XLAT(opt,:,:) lon2d = f->XLONG(0,:,:) else if (rank.eq.2) then lat2d = f->XLAT lon2d = f->XLONG else print ("WRF_resLamCon_c: unexpected lat/lon rank: rank="+rank) exit end if end if lat2d@units = "degrees_north" ; not needed lon2d@units = "degrees_east" dimll = dimsizes(lat2d) nlat = dimll(0) mlon = dimll(1) res@mpLimitMode = "Corners" res@mpLeftCornerLatF = lat2d(0,0) res@mpLeftCornerLonF = lon2d(0,0) res@mpRightCornerLatF = lat2d(nlat-1,mlon-1) res@mpRightCornerLonF = lon2d(nlat-1,mlon-1) res@mpCenterLonF = f@CEN_LON res@mpCenterLatF = f@CEN_LAT ; default if (res@mpProjection.eq."Mercator") then res@mpCenterLatF = 0.0 ; Cindy Bruyere MMM/WRF 24 Mar 2006 end if if (res@mpProjection.eq."LambertConformal") then res@mpLambertParallel1F = f@TRUELAT1 res@mpLambertParallel2F = f@TRUELAT2 if (isatt(f, "STAND_LON") ) then res@mpLambertMeridianF = f@STAND_LON ; use if present ; CB MMM/WRF 4 Aug 2006 else if (isatt(f, "CEN_LON") ) then res@mpLambertMeridianF = f@CEN_LON else print("WRF_map_c: STAND_LON and CEN_LON missing") end if end if end if res@mpFillOn = False ; turn off map fill res@mpOutlineDrawOrder = "PostDraw" ; draw continental outline last res@mpOutlineBoundarySets = "GeophysicalAndUSStates" ; state boundaries res@mpPerimDrawOrder = "PostDraw" ; force map perim ; commented 5/17/2007 ;;res@tfDoNDCOverlay = True ; True for 'native' grid ; some WRF are not native res@gsnAddCyclic = False ; data are not cyclic end ;************************************************************************* ; D. Shea ; interface for backward compatibility undef("WRF_resLamCon_c") procedure WRF_resLamCon_c (f:file, res:logical, opt) begin WRF_map_c (f, res, opt) end ;************************************************************************* ; D. Shea ; interface for newly named procedure undef("wrf_mapres_c") procedure wrf_mapres_c(f:file, res:logical, opt) begin WRF_map_c (f, res, opt) end ;************************************************************************* ; D. Shea ; single interface to convert WRF character variable "Times" ; to user specified numeric values ; ; M. Haley ; At some point we decided to rename this from WRF_Times to wrf_times_c ; Also added error check for opt. ; undef ("wrf_times_c") function wrf_times_c(Times:character, opt:integer) begin if (opt.ge.0 .and. opt.le.1) then return(WRF_Times2Udunits_c(Times, opt) ) end if if (opt.eq.2) then return(WRF_Times2double_c(Times, opt) ) end if if (opt.eq.3) then return(WRF_Times_to_ymdh(Times, opt) ) end if end