1 !*****************************************************************************!
2 ! Subroutine RD_GRIB2 !
5 ! Read one record from the input GRIB2 file. Based on the information in !
6 ! the GRIB2 header and the user-defined Vtable, decide whether the field in!
7 ! the GRIB2 record is one to process or to skip. If the field is one we !
8 ! want to keep, extract the data from the GRIB2 record, and store the data !
9 ! in the ungrib memory structure. !
13 ! junit : "Unit Number" to open and read from. Not really a Fortran !
14 ! unit number, since we do not do Fortran I/O for the GRIB2 !
15 ! files. Nor is it a UNIX File Descriptor returned from a C !
16 ! OPEN statement. It is really just an array index to the !
17 ! array (IUARR) where the UNIX File Descriptor values are !
19 ! gribflnm : File name to open, if it is not already open. !
20 ! debug_level : Integer for various amounts of printout. !
24 ! hdate : The (up to)19-character date of the field to process. !
25 ! grib_edition : Version of the gribfile (1 or 2) !
26 ! ireaderr : Error flag: 0 - no error on read from GRIB2 file. !
27 ! 1 - Hit the end of the GRIB2 file. !
28 ! 2 - The file GRIBFLNM we tried to open does !
32 ! Author: Paula McCaslin, NOAA/FSL, Sept 2004 !
33 ! Code is based on code developed by Steve Gilbert NCEP & Kevin Manning NCAR !
34 ! Adapted for WPS: Jim Bresch, NCAR/MMM. Sept 2006 !
35 !*****************************************************************************!
37 SUBROUTINE rd_grib2(junit, gribflnm, hdate,
38 & grib_edition, ireaderr, debug_level)
42 use table ! Included to define g2code
43 use gridinfo ! Included to define map%
44 use storage_module ! Included sub put_storage
47 real, allocatable, dimension(:) :: hold_array
48 parameter(msk1=32000,msk2=4000)
49 character(len=1),allocatable,dimension(:) :: cgrib
50 integer :: listsec0(3)
51 integer :: listsec1(13)
52 integer year, month, day, hour, minute, second, fcst
53 character(len=*) :: gribflnm
54 character(len=*) :: hdate
55 character(len=8) :: pabbrev
56 character(len=20) :: labbrev
57 character(len=80) :: tabbrev
58 integer :: lskip, lgrib
59 integer :: junit, itot, icount, iseek
60 integer :: grib_edition
61 integer :: i, j, ireaderr, ith , debug_level
63 logical :: unpack, expand
64 type(gribfield) :: gfld
65 ! For subroutine put_storage
69 character (len=9) :: my_field
70 character (len=8) :: tmp8
71 ! For subroutine outout
72 integer , parameter :: maxlvl = 100
73 real , dimension(maxlvl) :: plvl
75 integer , dimension(maxlvl) :: level_array
77 C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
82 hdate = '0000-00-00_00:00:00'
92 call mprintf(.true.,DEBUG,"Begin rd_grib2", newline=.true.)
94 !/* IOS Return Codes from BACIO: */
96 !/* -1 Tried to open read only _and_ write only */
97 !/* -2 Tried to read and write in the same call */
98 !/* -3 Internal failure in name processing */
99 !/* -4 Failure in opening file */
100 !/* -5 Tried to read on a write-only file */
101 !/* -6 Failed in read to find the 'start' location */
102 !/* -7 Tried to write to a read only file */
103 !/* -8 Failed in write to find the 'start' location */
104 !/* -9 Error in close */
105 !/* -10 Read or wrote fewer data than requested */
107 !if ireaderr =1 we have hit the end of a file.
108 !if ireaderr =2 we have hit the end of all the files.
111 ! Open a byte-addressable file.
112 CALL BAOPENR(junit,gribflnm,IOS)
116 ! Search opend file for the next GRIB2 messege (record).
117 call skgb(junit,iseek,msk1,lskip,lgrib)
119 ! Check for EOF, or problem
124 ! Check size, if needed allocate more memory.
125 if (lgrib.gt.currlen) then
126 if (allocated(cgrib)) deallocate(cgrib)
127 allocate(cgrib(lgrib),stat=is)
128 !print *,'G2 allocate(cgrib(lgrib)) status: ',IS
132 ! Read a given number of bytes from unblocked file.
133 call baread(junit,lskip,lgrib,lengrib,cgrib)
135 call mprintf ((lgrib.ne.lengrib),ERROR,
136 & "rd_grib2: IO Error. %i .ne. %i ", newline=.true.,
137 & i1=lgrib,i2=lengrib)
142 call mprintf (.true.,DEBUG,
143 & "G2 GRIB MESSAGE %i starts at %i ", newline=.true.,
144 & i1=icount,i2=lskip+1)
147 call gb_info(cgrib,lengrib,listsec0,listsec1,
148 & numfields,numlocal,maxlocal,ierr)
149 call mprintf((ierr.ne.0),ERROR,
150 & " ERROR querying GRIB2 message = %i",newline=.true.,i1=ierr)
153 grib_edition=listsec0(2)
154 if (grib_edition.ne.2) then
158 ! Additional print statments for developer.
159 !MGD if ( debug_level .GT. 100 ) then
160 !MGD print *,'G2 SECTION 0: ',(listsec0(j),j=1,3)
161 !MGD print *,'G2 SECTION 1: ',(listsec1(j),j=1,13)
162 !MGD print *,'G2 Contains ',numlocal,' Local Sections ',
163 !MGD & ' and ',numfields,' data fields.'
168 ! Once per file fill in date, model and projection values.
170 if (lskip.lt.10) then
172 ! Build the 19-character date string, based on GRIB2 header date
173 ! and time information, including forecast time information:
176 call gf_getfld(cgrib,lengrib,n,.FALSE.,expand,gfld,ierr)
177 year =gfld%idsect(6) !(FOUR-DIGIT) YEAR OF THE DATA
178 month =gfld%idsect(7) ! MONTH OF THE DATA
179 day =gfld%idsect(8) ! DAY OF THE DATA
180 hour =gfld%idsect(9) ! HOUR OF THE DATA
181 minute=gfld%idsect(10) ! MINUTE OF THE DATA
182 second=gfld%idsect(11) ! SECOND OF THE DATA
185 ! Parse the forecast time info from Sect 4.
186 if (gfld%ipdtnum.eq.0) then ! Product Definition Template 4.0
188 ! Extract forecast time.
189 fcst = gfld%ipdtmpl(9)
193 ! Compute valid time.
195 !print *, 'ymd',gfld%idsect(6),gfld%idsect(7),gfld%idsect(8)
196 !print *, 'hhmm ',gfld%idsect(9),gfld%idsect(10)
198 call build_hdate(hdate,year,month,day,hour,minute,second)
199 call mprintf(.true.,DEBUG,"G2 hdate = %s ", newline=.true.,
201 call geth_newdate(hdate,hdate,3600*fcst)
202 call mprintf(.true.,DEBUG,"G2 hdate (fcst?) = %s ",
203 & newline=.true., s1=hdate)
207 ! Indicator of the source (center) of the data.
208 icenter = gfld%idsect(1)
210 ! Indicator of model (or whatever) which generated the data.
211 iprocess = gfld%ipdtmpl(5)
214 if (icenter.eq.7) then
215 if (iprocess.eq.83 .or. iprocess.eq.84) then
216 map%source = 'NCEP NAM Model'
217 elseif (iprocess.eq.81) then
218 map%source = 'NCEP GFS Model'
219 elseif (iprocess.eq.96) then
220 map%source = 'NCEP GFS Model'
221 elseif (iprocess.eq.109) then
222 map%source = 'NCEP RTMA'
223 elseif (iprocess.eq.105) then
224 map%source = 'NCEP RUC Model'
225 elseif (iprocess.eq.140) then
226 map%source = 'NCEP NARR'
227 elseif (iprocess.eq.44) then
228 map%source = 'NCEP SST Analysis'
230 map%source = 'unknown model from NCEP'
231 call mprintf(.true.,STDOUT,
232 & "unknown model from NCEP %i ",newline=.true.,
234 call mprintf(.true.,LOGFILE,
235 & "unknown model from NCEP %i ",newline=.true.,
238 else if (icenter .eq. 57) then
239 if (iprocess .eq. 87) then
240 map%source = 'AFWA AGRMET'
244 else if (icenter .eq. 98) then
247 map%source = 'unknown model and orig center'
252 ! Store information about the grid on which the data is.
253 ! This stuff gets stored in the MAP variable, as defined in
256 map%startloc = 'SWCORNER'
257 map%grid_wind = .true.
259 if (gfld%igdtnum.eq.0) then ! Lat/Lon grid aka Cylindrical Equidistant
261 map%nx = gfld%igdtmpl(8)
262 map%ny = gfld%igdtmpl(9)
263 map%dx = gfld%igdtmpl(17)
264 map%dy = gfld%igdtmpl(18)
265 map%lat1 = gfld%igdtmpl(12)
266 map%lon1 = gfld%igdtmpl(13)
267 write(tmp8,'(b8.8)') gfld%igdtmpl(14)
268 if (tmp8(5:5) .eq. '0') map%grid_wind = .false.
269 map%r_earth = earth_radius (gfld%igdtmpl(1))
271 ! Scale dx/dy values to degrees, default range is 1e6.
272 if (map%dx.gt.10000) then
273 map%dx = map%dx/scale_factor
275 if (map%dy.gt.10000) then
276 map%dy = map%dy/scale_factor
279 ! Scale lat/lon values to 0-180, default range is 1e6.
280 if (map%lat1.ge.scale_factor) then
281 map%lat1 = map%lat1/scale_factor
283 if (map%lon1.ge.scale_factor) then
284 map%lon1 = map%lon1/scale_factor
287 ! The following is needed for NCEP GFS, 0.5 degree output. The j-scan is in the -y direction.
288 ! In WPS, the sign of dy indicates the direction of the scan.
289 write(tmp8,'(b8.8)') gfld%igdtmpl(19)
290 read(tmp8,'(1x,i1)') jscan
291 if ( jscan .eq. 0 .and. map%dy .gt. 0. ) then
292 map%dy = -1. * map%dy
294 ! if ( map%lat1 .gt. gfld%igdtmpl(15) .and.
295 ! & map%dy .gt. 0. ) then
296 ! map%dy = -1. * map%dy
297 ! write(6,*) 'Resetting map%dy for iprocess = ',iprocess
300 elseif (gfld%igdtnum.eq.20) then ! Polar-Stereographic Grid.
302 map%nx = gfld%igdtmpl(8)
303 map%ny = gfld%igdtmpl(9)
304 map%lov = gfld%igdtmpl(14) / scale_factor
307 map%dx = gfld%igdtmpl(15) / scale_factor
308 map%dy = gfld%igdtmpl(16) / scale_factor
309 map%lat1 = gfld%igdtmpl(10) / scale_factor
310 map%lon1 = gfld%igdtmpl(11) / scale_factor
311 write(tmp8,'(b8.8)') gfld%igdtmpl(12)
312 if (tmp8(5:5) .eq. '0') map%grid_wind = .false.
313 map%r_earth = earth_radius (gfld%igdtmpl(1))
315 elseif (gfld%igdtnum.eq.30) then ! Lambert Conformal Grid
317 map%nx = gfld%igdtmpl(8)
318 map%ny = gfld%igdtmpl(9)
319 map%lov = gfld%igdtmpl(14) / scale_factor
320 map%truelat1 = gfld%igdtmpl(19) / scale_factor
321 map%truelat2 = gfld%igdtmpl(20) / scale_factor
322 map%dx = gfld%igdtmpl(15) / scale_factor
323 map%dy = gfld%igdtmpl(16) / scale_factor
324 map%lat1 = gfld%igdtmpl(10) / scale_factor
325 map%lon1 = gfld%igdtmpl(11) / scale_factor
326 write(tmp8,'(b8.8)') gfld%igdtmpl(12)
327 if (tmp8(5:5) .eq. '0') map%grid_wind = .false.
328 map%r_earth = earth_radius (gfld%igdtmpl(1))
330 elseif(gfld%igdtnum.eq.40) then ! Gaussian Grid (we will call it lat/lon)
332 map%nx = gfld%igdtmpl(8) ! Ni - # of points along a parallel
333 map%ny = gfld%igdtmpl(9) ! Nj - # of points along meridian
334 map%dx = gfld%igdtmpl(17) ! Di - i direction increment
335 map%dy = gfld%igdtmpl(18) ! N - # of parallels between pole and equator
336 map%lat1 = gfld%igdtmpl(12) ! La1 - lat of 1st grid point
337 map%lon1 = gfld%igdtmpl(13) ! Lo1 - lon of 1st grid point
338 write(tmp8,'(b8.8)') gfld%igdtmpl(14) ! resolution/component flag
339 if (tmp8(5:5) .eq. '0') map%grid_wind = .false.
340 map%r_earth = earth_radius (gfld%igdtmpl(1))
342 ! Scale dx/dy values to degrees, default range is 1e6.
343 if (map%dx.gt.10000) then
344 map%dx = map%dx/scale_factor
346 if (map%dy.gt.10000) then
347 map%dy = (map%dy/scale_factor)*(-1)
350 ! Scale lat/lon values to 0-180, default range is 1e6.
351 if (map%lat1.ge.scale_factor) then
352 map%lat1 = map%lat1/scale_factor
354 if (map%lon1.ge.scale_factor) then
355 map%lon1 = map%lon1/scale_factor
357 if ( debug_level .gt. 2 ) then
358 call mprintf(.true.,DEBUG,
359 & "Gaussian Grid: Dx,Dy,lat,lon,nlats %f %f %f %f %i ",
360 & newline=.true.,f1=map%dx,f2=map%dy,f3=map%lat1,f4=map%lon1,
365 call mprintf(.true.,STDOUT,"GRIB2 Unknown Projection: %i",
366 & newline=.true.,i1=gfld%igdtnum)
367 call mprintf(.true.,STDOUT,
368 & "see Code Table 3.1: Grid Definition Template Number",
370 call mprintf(.true.,LOGFILE,
371 & "GRIB2 Unknown Projection: %i",
372 & newline=.true.,i1=gfld%igdtnum)
373 call mprintf(.true.,LOGFILE,
374 & "see Code Table 3.1: Grid Definition Template Number",
378 if (icenter.eq.7) then
379 call ncep_grid_num (gfld%igdtnum)
382 ! Deallocate arrays decoding GRIB2 record.
388 ! Continue to unpack GRIB2 field.
389 do n=1,numfields ! e.g. U and V would =2, otherwise its usually =1
390 call gf_getfld(cgrib,lengrib,n,.FALSE.,expand,gfld,ierr)
392 write(*,*) ' ERROR extracting field gf_getfld = ',ierr
396 ! ------------------------------------
397 ! Additional print information for developer.
398 if ( debug_level .GT. 1000 ) then
400 !MGD print *,'G2 FIELD ',n
402 !MGD print *,'G2 SECTION 0: ',gfld%discipline,gfld%version
403 !MGD print *,'G2 SECTION 1: ',(gfld%idsect(j),j=1,gfld%idsectlen)
405 !MGD if ( associated(gfld%local).AND.gfld%locallen.gt.0 ) then
406 !MGD print *,'G2 SECTION 2: ',(gfld%local(j),j=1,gfld%locallen)
408 !MGD print *,'G2 SECTION 3: ',gfld%griddef,gfld%ngrdpts,
409 !MGD & gfld%numoct_opt,gfld%interp_opt,
411 !MGD print *,'G2 GRID TEMPLATE 3.',gfld%igdtnum,': ',
412 !MGD & (gfld%igdtmpl(j),j=1,gfld%igdtlen)
413 !MGD if ( gfld%num_opt .eq. 0 ) then
414 !MGD print *,'G2 NO Section 3 List Defining No. of Data Points.'
416 !MGD print *,'G2 Section 3 Optional List: ',
417 !MGD & (gfld%list_opt(j),j=1,gfld%num_opt)
419 !MGD print *,'G2 PRODUCT TEMPLATE 4.',gfld%ipdtnum,': ',
420 !MGD & (gfld%ipdtmpl(j),j=1,gfld%ipdtlen)
422 pabbrev=param_get_abbrev(gfld%discipline,gfld%ipdtmpl(1),
424 !call prlevel(gfld%ipdtnum,gfld%ipdtmpl,labbrev)
425 !call prvtime(gfld%ipdtnum,gfld%ipdtmpl,listsec1,tabbrev)
426 !MGD print *,'G2 TEXT: ',pabbrev,trim(labbrev)," ",trim(tabbrev)
428 !MGD if ( gfld%num_coord .eq. 0 ) then
429 !MGD print *,'G2 NO Optional Vertical Coordinate List.'
431 !MGD print *,'G2 Section 4 Optional Coordinates: ',
432 !MGD & (gfld%coord_list(j),j=1,gfld%num_coord)
434 if ( gfld%ibmap .ne. 255 ) then
435 call mprintf(.true.,DEBUG,
436 & 'G2 Num. of Data Points = %i with BIT-MAP %i',
437 & newline=.true., i1=gfld%ndpts, i2=gfld%ibmap)
439 call mprintf(.true.,DEBUG,
440 & 'G2 Num. of Data Points = %i NO BIT-MAP',
441 & newline=.true., i1=gfld%ndpts)
443 !MGD print *,'G2 DRS TEMPLATE 5.',gfld%idrtnum,': ',
444 !MGD & (gfld%idrtmpl(j),j=1,gfld%idrtlen)
449 if (gfld%fld(j).gt.fldmax) fldmax=gfld%fld(j)
450 if (gfld%fld(j).lt.fldmin) fldmin=gfld%fld(j)
454 !MGD print *,'G2 Data Values:'
455 call mprintf(.true.,DEBUG,'G2 MIN=%f AVE=%f MAX=%f',
456 & newline=.true., f1=fldmin, f2=sum/gfld%ndpts, f3=fldmax)
457 !do j=1,gfld%ndpts\20
458 ! write(*,*) j, gfld%fld(j)
460 endif ! Additional Print information
461 ! ------------------------------------
464 ! write(6,'(a10,4i8)') namvar(i),(g2code(j,i),j=1,4)
466 !MGD if (debug_level .gt. 50) then
467 !MGD write(6,*) 'looking for ',gfld%discipline,gfld%ipdtmpl(1),
468 !MGD & gfld%ipdtmpl(2),gfld%ipdtmpl(10)
471 ! Test this data record against list of desired variables
474 MATCH_LOOP: do i=1,maxvar ! Max variables found in Vtable,
475 ! maxvar is defined in table.mod
477 if ( gfld%discipline .eq. g2code(1,i) .and. !Discipline
478 & gfld%ipdtmpl(1) .eq. g2code(2,i) .and. !Category
479 & gfld%ipdtmpl(2) .eq. g2code(3,i) .and. !Parameter
480 & gfld%ipdtmpl(10) .eq. g2code(4,i)) then !Elevation
483 call gf_getfld(cgrib,lengrib,n,.TRUE.,expand,gfld,ierr)
484 pabbrev=param_get_abbrev(gfld%discipline,gfld%ipdtmpl(1),
487 !my_field (e.g. RH, TMP, similar to, but not the same as pabbrev)
490 !MGD if (debug_level .gt. 50) then
491 !MGD write(6,*) 'namvar(i) = ',namvar(i),' pabbrev = ',pabbrev
492 !MGD write(6,*) 'Parameter = ',gfld%ipdtmpl(2)
496 ! need to match up soil levels with those requested.
497 ! For the Vtable levels, -88 = all levels, -99 = missing. The units
498 ! vary depending on the level code (e.g. 106 = cm, 103 = m).
499 if ( gfld%ipdtmpl(10) .eq. 106 ) then
500 TMP8LOOP: do j = 1, maxvar
501 if ((g2code(4,j) .eq. 106) .and.
502 & (gfld%ipdtmpl(2) .eq. g2code(3,j)) .and.
503 & (gfld%ipdtmpl(12) .eq. level1(j)) .and.
504 & ((gfld%ipdtmpl(15) .eq. level2(j)) .or.
505 & (level2(j) .le. -88))) then
510 if (j .gt. maxvar ) then
511 write(6,'(a,i6,a,i6,a)') 'Subsoil level ',
512 & gfld%ipdtmpl(12),' to ',gfld%ipdtmpl(15),
513 & ' in the GRIB2 file, was not found in the Vtable'
516 !MGD if (debug_level .gt. 50) write(6,*) 'my_field is now ',my_field
519 ! Level (eg. 10000 mb)
520 if(gfld%ipdtmpl(10).eq.100) then
521 ! Pressure level (range from 1000mb to 0mb)
522 level=gfld%ipdtmpl(12)
523 elseif(gfld%ipdtmpl(10).eq.105) then
524 ! Hybrid level (range from 1 to N)
525 level=gfld%ipdtmpl(12)
526 elseif(gfld%ipdtmpl(10).eq.104) then
527 ! Sigma level (range from 10000 to 0)
528 level=gfld%ipdtmpl(12)
529 elseif(gfld%ipdtmpl(10).eq.101) then
532 elseif(gfld%ipdtmpl(10).eq.106.or.
533 & gfld%ipdtmpl(10).eq.1) then
534 ! Misc near ground/surface levels
537 ! Misc near ground/surface levels
542 ! Store the unpacked 2D slab from the GRIB2 record
543 allocate(hold_array(gfld%ngrdpts))
545 hold_array(j)=gfld%fld(j)
548 ! Some grids need to be reordered. Until we get an example, this is
550 ! call reorder_it (hold_array, map%nx, map%ny, map%dx,
553 ! When we have reached this point, we have a data array ARRAY
554 ! which has some data we want to save, with field name FIELD
555 ! at pressure level LEVEL (Pa). Dimensions of this data are
556 ! map%nx and map%ny. Put this data into storage.
558 !print *,'call put_storage',iplvl,my_field,hold_array(55),ith
559 !e.g. call put_storage(200100, 'RH', my_field, 1, ith)
560 call put_storage(iplvl,my_field,
561 & reshape(hold_array(1:map%nx*map%ny),
562 & (/map%nx, map%ny/)), map%nx,map%ny)
563 deallocate(hold_array)
565 ! If Specific Humidity is present on hybrid levels AND
566 ! upper-air RH is missing, see if we can compute RH from
568 if (.not. is_there(iplvl, 'RH') .and.
569 & is_there(iplvl, 'SH') .and.
570 & is_there(iplvl, 'TT') .and.
571 & is_there(iplvl, 'P')) then
572 call g2_compute_rh_spechumd_upa(map%nx,map%ny,iplvl)
573 !call llstor_remove(iplvl, 'SH') !We are done with SH
579 endif ! Selected param.
584 ! Deallocate arrays decoding GRIB2 record.
593 if ( debug_level .gt. 100 ) then
594 call mprintf (.true.,DEBUG,
595 & "G2 total number of fields found = %i ",newline=.true.,i1=itot)
598 CALL BACLOSE(junit,IOS)
600 nullify(gfld%local) ! must be nullified before opening next file
603 call mprintf (.true.,DEBUG,"open status failed because %i ",
604 & newline=.true., i1=ios)
605 hdate = '9999-99-99_99:99:99'
607 endif ! ireaderr check
609 END subroutine rd_grib2
611 !*****************************************************************************!
612 ! Subroutine edition_num !
615 ! Read one record from the input GRIB2 file. Based on the information in !
616 ! the GRIB2 header and the user-defined Vtable, decide whether the field in!
617 ! the GRIB2 record is one to process or to skip. If the field is one we !
618 ! want to keep, extract the data from the GRIB2 record, and pass the data !
619 ! back to the calling routine. !
623 ! JUNIT : "Unit Number" to open and read from. Not really a Fortran !
624 ! unit number, since we do not do Fortran I/O for the GRIB2 !
625 ! files. Nor is it a UNIX File Descriptor returned from a C !
626 ! OPEN statement. It is really just an array index to the !
627 ! array (IUARR) where the UNIX File Descriptor values are !
629 ! GRIB2FILE: File name to open, if it is not already open. !
632 ! GRIB_EDITION: Set to 1 for GRIB and set to 2 for GRIB2 !
633 ! IERR : Error flag: 0 - no error on read from GRIB2 file. !
634 ! 1 - Hit the end of the GRIB2 file. !
635 ! 2 - The file GRIBFLNM we tried to open does !
637 ! Author: Paula McCaslin !
640 !*****************************************************************************!
642 SUBROUTINE edition_num(junit, gribflnm,
643 & grib_edition, ireaderr)
649 parameter(msk1=32000,msk2=4000)
650 character(len=1),allocatable,dimension(:) :: cgrib
651 integer :: listsec0(3)
652 integer :: listsec1(13)
653 character(len=*) :: gribflnm
654 integer :: lskip, lgrib
656 integer :: grib_edition
657 integer :: i, j, ireaderr
660 character(len=4) :: ctemp
661 character(len=4),parameter :: grib='GRIB',c7777='7777'
663 C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
673 !/* IOS Return Codes from BACIO: */
674 !/* 0 All was well */
675 !/* -1 Tried to open read only _and_ write only */
676 !/* -2 Tried to read and write in the same call */
677 !/* -3 Internal failure in name processing */
678 !/* -4 Failure in opening file */
679 !/* -5 Tried to read on a write-only file */
680 !/* -6 Failed in read to find the 'start' location */
681 !/* -7 Tried to write to a read only file */
682 !/* -8 Failed in write to find the 'start' location */
683 !/* -9 Error in close */
684 !/* -10 Read or wrote fewer data than requested */
686 !if ireaderr =1 we have hit the end of a file.
687 !if ireaderr =2 we have hit the end of all the files.
688 !if ireaderr =3 beginning characters 'GRIB' not found
690 ! Open a byte-addressable file.
691 CALL BAOPENR(junit,gribflnm,IOS)
694 ! Search opend file for the next GRIB2 messege (record).
695 call skgb(junit,iseek,msk1,lskip,lgrib)
697 ! Check for EOF, or problem
698 call mprintf((lgrib.eq.0),ERROR,
699 & "Grib2 file or date problem, stopping in edition_num.",
702 ! Check size, if needed allocate more memory.
703 if (lgrib.gt.currlen) then
704 if (allocated(cgrib)) deallocate(cgrib)
705 allocate(cgrib(lgrib),stat=is)
709 ! Read a given number of bytes from unblocked file.
710 call baread(junit,lskip,lgrib,lengrib,cgrib)
712 ! Check for beginning of GRIB message in the first 100 bytes
715 ctemp=cgrib(j)//cgrib(j+1)//cgrib(j+2)//cgrib(j+3)
716 if (ctemp.eq.grib ) then
721 if (istart.eq.0) then
723 print*, "The beginning 4 characters >GRIB< were not found."
726 ! Unpack Section 0 - Indicator Section to extract GRIB edition field
728 call gbyte(cgrib,discipline,iofst,8) ! Discipline
730 call gbyte(cgrib,grib_edition,iofst,8) ! GRIB edition number
732 print *, 'ungrib - grib edition num', grib_edition
733 CALL BACLOSE(junit,IOS)
735 else if (ios .eq. -4) then
736 call mprintf(.true.,ERROR,
737 & "edition_num: unable to open %s",newline=.true.,s1=gribflnm)
739 print *,'edition_num: open status failed because',ios,gribflnm
741 endif ! ireaderr check
743 END subroutine edition_num
745 !*****************************************************************************!
747 SUBROUTINE g2_compute_rh_spechumd_upa(ix, jx, iiplvl)
748 ! Compute relative humidity from specific humidity in the upper air.
753 real :: lat1, lon1, dx, dy
754 real, dimension(ix,jx) :: T, P, RH, Q
756 real, parameter :: svp1=611.2
757 real, parameter :: svp2=17.67
758 real, parameter :: svp3=29.65
759 real, parameter :: svpt0=273.15
760 real, parameter :: eps = 0.622
762 real startlat, startlon, deltalat, deltalon
764 call get_storage(iiplvl, 'P', P, ix, jx)
765 call get_storage(iiplvl, 'TT', T, ix, jx)
766 call get_storage(iiplvl, 'SH', Q, ix, jx)
768 rh=1.E2*(p*q/(q*(1.-eps)+eps))/(svp1*exp(svp2*(t-svpt0)/(T-svp3)))
770 call put_storage(iiplvl, 'RH', rh, ix, jx)
772 end subroutine g2_compute_rh_spechumd_upa
774 !*****************************************************************************!
776 subroutine ncep_grid_num (pnum)
778 ! Grib2 doesn't have a grid-number entry, so we have to figure it out
780 use gridinfo ! Included to define map%
782 real, parameter :: eps = .01
783 character (len=8) :: tmp8
785 ! write(6,*) 'begin ncep_grid_num'
786 ! write(6,*) 'dx = ',map%dx,' pnum = ',pnum,' nx = ',map%nx
788 if (pnum .eq. 30) then
789 if ( abs(map%dx - 12.19058) .lt. eps .and. map%nx .eq. 614) then
790 write(tmp8,'("GRID 218")')
791 else if (abs(map%dx - 40.63525) .lt. eps
792 & .and. map%nx .eq. 185) then
793 write(tmp8,'("GRID 212")')
794 else if (abs(map%dx - 40.63525) .lt. eps
795 & .and. map%nx .eq. 151) then
796 write(tmp8,'("GRID 236")')
797 else if (abs(map%dx - 81.2705) .lt. eps
798 & .and. map%nx .eq. 93) then
799 write(tmp8,'("GRID 211")')
800 else if (abs (map%dx - 32.46341) .lt. eps
801 & .and. map%nx .eq. 349) then
802 write(tmp8,'("GRID 221")')
803 else if (abs(map%dx - 20.317625) .lt. eps
804 & .and. map%nx .eq. 301) then
805 write(tmp8,'("GRID 252")')
807 else if (pnum .eq. 20) then
808 if (abs(map%dx - 15.0) .lt. eps) then
809 write(tmp8,'("GRID 88")')
811 else if (pnum .eq. 0) then
812 if (abs(map%dx - 1.) .lt. eps .and. map%nx .eq. 360) then
813 write(tmp8,'("GRID 3")')
814 else if (abs(map%dx - 0.5) .lt. eps .and. map%nx .eq. 720) then
815 write(tmp8,'("GRID 4")')
818 map%source(25:32) = tmp8
819 ! write(6,*) 'map%source = ',map%source
820 end subroutine ncep_grid_num
821 !*****************************************************************************!
823 function earth_radius (icode)
824 ! Grib2 Code Table 3.2. Returns the spherical earth's radius in km.
828 if ( icode .eq. 0 ) then
829 earth_radius = 6367470. * .001
830 else if ( icode .eq. 6 ) then
831 earth_radius = 6371229. * .001
833 call mprintf(.true.,ERROR,
834 & "unknown earth radius for code %i",newline=.true.,i1=icode)
836 end function earth_radius