NCEPLIBS-bufr  12.3.0
cftbvs.F90
Go to the documentation of this file.
1 
5 
21 recursive real*8 function pkftbv(nbits,ibit) result(r8val)
22 
23  use modv_vars, only: im8b, bmiss
24 
25  implicit none
26 
27  integer, intent(in) :: nbits, ibit
28  integer my_nbits, my_ibit
29 
30  ! Check for I8 integers.
31 
32  if(im8b) then
33  im8b=.false.
34  call x84(nbits,my_nbits,1)
35  call x84(ibit,my_ibit,1)
36  r8val=pkftbv(my_nbits,my_ibit)
37  im8b=.true.
38  return
39  endif
40 
41  if((nbits<=0).or.(ibit<=0).or.(ibit>nbits)) then
42  r8val = bmiss
43  else
44  r8val = (2.)**(nbits-ibit)
45  endif
46 
47  return
48 end function pkftbv
49 
67 recursive subroutine upftbv(lunit,nemo,val,mxib,ibit,nib)
68 
69  use bufrlib
70 
71  use modv_vars, only: im8b
72 
73  use moda_tababd
74 
75  implicit none
76 
77  integer, intent(in) :: lunit, mxib
78  integer, intent(out) :: ibit(*), nib
79  integer my_lunit, my_mxib, lun, il, im, idn, i, n, nbits, iersn, lcn, bort_target_set
80 
81  character*(*), intent(in) :: nemo
82  character*128 bort_str
83  character*12 cnemo
84  character tab
85 
86  real*8, intent(in) :: val
87  real*8 r8val, r82i
88 
89  ! Check for I8 integers.
90 
91  if(im8b) then
92  im8b=.false.
93  call x84(lunit,my_lunit,1)
94  call x84(mxib,my_mxib,1)
95  call upftbv(my_lunit,nemo,val,my_mxib*2,ibit,nib)
96  if (nib>0 .and. nib<=my_mxib*2) call x48(ibit(1),ibit(1),nib)
97  call x48(nib,nib,1)
98  im8b=.true.
99  return
100  endif
101 
102  ! If we're catching bort errors, set a target return location if one doesn't already exist.
103 
104  if (bort_target_set() == 1) then
105  call strsuc(nemo,cnemo,lcn)
106  call catch_bort_upftbv_c(lunit,cnemo,lcn,val,ibit,mxib,nib)
107  call bort_target_unset
108  return
109  endif
110 
111  nib = 0
112 
113  ! Perform some sanity checks.
114 
115  call status(lunit,lun,il,im)
116  if(il==0) call bort('BUFRLIB: UPFTBV - INPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR INPUT')
117 
118  call nemtab(lun,nemo,idn,tab,n)
119  if(n==0) then
120  write(bort_str,'("BUFRLIB: UPFTBV - MNEMONIC ",A," NOT FOUND IN TABLE B")') nemo
121  call bort(bort_str)
122  endif
123  if(tabb(n,lun)(71:74)/='FLAG') then
124  write(bort_str,'("BUFRLIB: UPFTBV - MNEMONIC ",A," IS NOT A FLAG TABLE")') nemo
125  call bort(bort_str)
126  endif
127 
128  ! Figure out which bits are set.
129 
130  r8val = val
131  call strnum(tabb(n,lun)(110:112),nbits,iersn)
132  do i=(nbits-1),0,-1
133  r82i = (2.)**i
134  if(abs(r8val-r82i)<(0.005)) then
135  nib = nib + 1
136  if(nib>mxib) call bort('BUFRLIB: UPFTBV - IBIT ARRAY OVERFLOW')
137  ibit(nib) = nbits-i
138  return
139  elseif(r82i<r8val) then
140  nib = nib + 1
141  if(nib>mxib) call bort('BUFRLIB: UPFTBV - IBIT ARRAY OVERFLOW')
142  ibit(nib) = nbits-i
143  r8val = r8val - r82i
144  endif
145  enddo
146 
147  return
148 end subroutine upftbv
149 
228 recursive subroutine getcfmng ( lunit, nemoi, ivali, nemod, ivald, cmeang, lnmng, iret )
229 
230  use bufrlib
231 
232  use modv_vars, only: im8b
233 
234  use moda_tababd
235  use moda_tablef
236 
237  implicit none
238 
239  integer, intent(in) :: lunit, ivali, ivald
240  integer, intent(out) :: lnmng, iret
241  integer ifxyd(10), my_lunit, my_ivali, my_ivald, lun, il, im, itmp, ii, ifxyi, lcmg, n, ntg, iret2, ierbd, ifxy, ireadmt, &
242  lcni, lcnd, lcmgc, bort_target_set
243 
244  character*(*), intent(in) :: nemoi, nemod
245  character*(*), intent(out) :: cmeang
246  character*128 bort_str
247  character*9 cnemoi, cnemod
248  character*8 nemo, my_nemoi, my_nemod
249  character tab
250  character*(:), allocatable :: cmeang_c
251 
252  ! Check for I8 integers
253 
254  if(im8b) then
255  im8b=.false.
256  call x84(lunit,my_lunit,1)
257  call x84(ivali,my_ivali,1)
258  call x84(ivald,my_ivald,1)
259  call getcfmng(my_lunit,nemoi,my_ivali,nemod,my_ivald,cmeang,lnmng,iret)
260  call x48(lnmng,lnmng,1)
261  call x48(iret,iret,1)
262  im8b=.true.
263  return
264  endif
265 
266  cmeang = ' '
267  lcmg = len( cmeang )
268 
269  ! If we're catching bort errors, set a target return location if one doesn't already exist.
270 
271  if (bort_target_set() == 1) then
272  call strsuc(nemoi,cnemoi,lcni)
273  call strsuc(nemod,cnemod,lcnd)
274  lcmgc = lcmg + 1 ! Allow extra byte in cmeang_c for the trailing null in C
275  allocate(character*(lcmgc) :: cmeang_c)
276  call catch_bort_getcfmng_c(lunit,cnemoi,lcni,ivali,cnemod,lcnd,ivald,cmeang_c,lcmgc,lnmng,iret)
277  cmeang(1:lnmng) = cmeang_c(1:lnmng)
278  deallocate(cmeang_c)
279  call bort_target_unset
280  return
281  endif
282 
283  call status ( lunit, lun, il, im )
284  if ( il == 0 ) call bort('BUFRLIB: GETCFMNG - INPUT BUFR FILE IS CLOSED, IT MUST BE OPEN FOR INPUT')
285  if ( il > 0 ) call bort('BUFRLIB: GETCFMNG - INPUT BUFR FILE IS OPEN FOR OUTPUT, IT MUST BE OPEN FOR INPUT')
286  if ( im == 0 ) call bort('BUFRLIB: GETCFMNG - A MESSAGE MUST BE OPEN IN INPUT BUFR FILE, NONE ARE')
287 
288  ! Make sure the appropriate code/flag information has already been read into internal memory.
289 
290  if ( cdmf /= 'Y' ) call bort('BUFRLIB: GETCFMNG - TO USE THIS SUBROUTINE, MUST '// &
291  'FIRST CALL SUBROUTINE CODFLG WITH INPUT ARGUMENT SET TO Y')
292 
293  itmp = ireadmt( lun )
294 
295  ! Check the validity of the input mnemonic(s). Include special handling for originating centers, originating subcenters, data
296  ! types and data subtypes, since those can be reported in Section 1 of a BUFR message as well as in Section 3, so if a user
297  ! requests those mnemonics we can't necessarily assume they came from within Section 3.
298 
299  my_nemoi = ' '
300  do ii = 1, min( 8, len( nemoi ) )
301  my_nemoi(ii:ii) = nemoi(ii:ii)
302  end do
303  my_nemod = ' '
304  do ii = 1, min( 8, len( nemod ) )
305  my_nemod(ii:ii) = nemod(ii:ii)
306  end do
307  if ( my_nemoi(1:4) == 'GSES' ) then
308  if ( ( my_nemod(1:6) == 'GCLONG' ) .or. ( my_nemod(1:4) == 'OGCE' ) .or. ( my_nemod(1:5) == 'ORIGC' ) ) then
309  ifxyi = ifxy( '001034' )
310  ifxyd(1) = ifxy( '001035' )
311  else
312  lnmng = min( 24, lcmg )
313  if ( lnmng == 24 ) then
314  iret = 3
315  cmeang(1:24) = 'GCLONG OGCE ORIGC '
316  else
317  iret = -1
318  end if
319  return
320  end if
321  else if ( my_nemoi(1:6) == 'GCLONG' ) then
322  ifxyi = ifxy( '001031' )
323  ifxyd(1) = (-1)
324  else if ( my_nemoi(1:4) == 'OGCE' ) then
325  ifxyi = ifxy( '001033' )
326  ifxyd(1) = (-1)
327  else if ( my_nemoi(1:5) == 'ORIGC' ) then
328  ifxyi = ifxy( '001035' )
329  ifxyd(1) = (-1)
330  else if ( ( my_nemoi(1:7) == 'TABLASS' ) .or. ( my_nemoi(1:7) == 'TABLASL' ) ) then
331  if ( ( my_nemod(1:6) == 'TABLAT' ) ) then
332  if ( my_nemoi(1:7) == 'TABLASS' ) then
333  ifxyi = ifxy( '055021' )
334  else
335  ifxyi = ifxy( '055022' )
336  endif
337  ifxyd(1) = ifxy( '055020' )
338  else
339  lnmng = min( 8, lcmg )
340  if ( lnmng == 8 ) then
341  iret = 1
342  cmeang(1:8) = 'TABLAT '
343  else
344  iret = -1
345  end if
346  return
347  end if
348  else if ( my_nemoi(1:6) == 'TABLAT' ) then
349  ifxyi = ifxy( '055020' )
350  ifxyd(1) = (-1)
351  else
352  call parstr ( my_nemoi, nemo, 1, ntg, ' ', .true. )
353  call nemtab ( lun, nemo, ifxyi, tab, n )
354  if ( ( n == 0 ) .or. ( tab /= 'B' ) ) then
355  write(bort_str,'("BUFRLIB: GETCFMNG - MNEMONIC ",A," NOT FOUND IN TABLE B")') nemo
356  call bort(bort_str)
357  endif
358  if ( ( tabb( n, lun )(71:74) /= 'CODE' ) .and. ( tabb( n, lun )(71:74) /= 'FLAG' ) ) then
359  write(bort_str,'("BUFRLIB: GETCFMNG - MNEMONIC ",A," IS NOT A CODE OR FLAG TABLE")') nemo
360  call bort(bort_str)
361  endif
362  if ( my_nemod(1:1) /= ' ' ) then
363  call parstr ( my_nemod, nemo, 1, ntg, ' ', .true. )
364  call nemtab ( lun, nemo, ifxyd(1), tab, n )
365  if ( ( n == 0 ) .or. ( tab /= 'B' ) ) then
366  write(bort_str,'("BUFRLIB: GETCFMNG - MNEMONIC ",A," NOT FOUND IN TABLE B")') nemo
367  call bort(bort_str)
368  endif
369  if ( ( tabb( n, lun )(71:74) /= 'CODE' ) .and. ( tabb( n, lun )(71:74) /= 'FLAG' ) ) then
370  write(bort_str,'("BUFRLIB: GETCFMNG - MNEMONIC ",A," IS NOT A CODE OR FLAG TABLE")') nemo
371  call bort(bort_str)
372  endif
373  else
374  ifxyd(1) = (-1)
375  end if
376  end if
377 
378  ! Search the internal table for the requested meaning.
379 
380  call srchtbf_c ( ifxyi, ivali, ifxyd(1), 10, ivald, cmeang, lcmg, lnmng, iret )
381  if ( iret <= 0 ) return
382 
383  ! The meaning of this value is dependent on the value of another mnemonic in the report.
384 
385  iret2 = iret
386  lnmng = 0
387  iret = 0
388  do ii = 1, iret2
389  call numtbd ( lun, ifxyd(ii), nemo, tab, ierbd )
390  if ( ( ierbd > 0 ) .and. ( tab == 'B' ) .and. ( lcmg >= ( lnmng + 8 ) ) ) then
391  iret = iret + 1
392  cmeang(lnmng+1:lnmng+8) = nemo
393  lnmng = lnmng + 8
394  end if
395  end do
396  if ( iret == 0 ) iret = -1
397 
398  return
399 end subroutine getcfmng
400 
420 recursive subroutine ufbqcd(lunit,nemo,iqcd)
421 
422  use bufrlib
423 
424  use modv_vars, only: im8b
425 
426  implicit none
427 
428  integer, intent(in) :: lunit
429  integer, intent(out) :: iqcd
430  integer my_lunit, lun, il, im, idn, iret, lcn, bort_target_set
431 
432  character*(*), intent(in) :: nemo
433  character*128 bort_str
434  character*12 cnemo
435  character*6 fxy, adn30
436  character tab
437 
438  ! Check for I8 integers
439 
440  if(im8b) then
441  im8b=.false.
442  call x84(lunit,my_lunit,1)
443  call ufbqcd(my_lunit,nemo,iqcd)
444  call x48(iqcd,iqcd,1)
445  im8b=.true.
446  return
447  endif
448 
449  ! If we're catching bort errors, set a target return location if one doesn't already exist.
450 
451  if (bort_target_set() == 1) then
452  call strsuc(nemo,cnemo,lcn)
453  call catch_bort_ufbqcd_c(lunit,cnemo,iqcd,lcn)
454  call bort_target_unset
455  return
456  endif
457 
458  call status(lunit,lun,il,im)
459  if(il==0) call bort('BUFRLIB: UFBQCD - BUFR FILE IS CLOSED, IT MUST BE OPEN')
460 
461  call nemtab(lun,nemo,idn,tab,iret)
462  if(tab/='D') then
463  write(bort_str,'("BUFRLIB: UFBQCD - INPUT MNEMONIC ",A," NOT DEFINED AS A SEQUENCE DESCRIPTOR IN BUFR TABLE")') nemo
464  call bort(bort_str)
465  endif
466 
467  fxy = adn30(idn,6)
468  if(fxy(2:3)/='63') then
469  write(bort_str,'("BUFRLIB: UFBQCD - BUFR TABLE SEQ. DESCRIPTOR '// &
470  'ASSOC. WITH INPUT MNEMONIC ",A," HAS INVALID CATEGORY ",A," - CATEGORY MUST BE 63")') nemo, fxy(2:3)
471  call bort(bort_str)
472  endif
473  read(fxy(4:6),'(I3)') iqcd
474 
475  return
476 end subroutine ufbqcd
477 
492 recursive subroutine ufbqcp(lunit,iqcp,nemo)
493 
494  use bufrlib
495 
496  use modv_vars, only: im8b
497 
498  implicit none
499 
500  integer, intent(in) :: lunit, iqcp
501  integer my_lunit, my_iqcp, lun, il, im, idn, iret, ifxy, lnm, ncn, bort_target_set
502 
503  character*(*), intent(out) :: nemo
504  character*9 cnemo
505  character tab
506 
507  ! Check for I8 integers
508 
509  if(im8b) then
510  im8b=.false.
511  call x84(lunit,my_lunit,1)
512  call x84(iqcp,my_iqcp,1)
513  call ufbqcp(my_lunit,my_iqcp,nemo)
514  im8b=.true.
515  return
516  endif
517 
518  ! If we're catching bort errors, set a target return location if one doesn't already exist.
519 
520  if (bort_target_set() == 1) then
521  call catch_bort_ufbqcp_c(lunit,iqcp,cnemo,len(cnemo),ncn)
522  nemo = ' '
523  lnm = min(len(nemo),ncn)
524  nemo(1:lnm) = cnemo(1:lnm)
525  call bort_target_unset
526  return
527  endif
528 
529  call status(lunit,lun,il,im)
530  if(il==0) call bort('BUFRLIB: UFBQCP - BUFR FILE IS CLOSED, IT MUST BE OPEN')
531 
532  idn = ifxy('363000')+iqcp
533  call numtab(lun,idn,nemo,tab,iret)
534 
535  return
536 end subroutine ufbqcp
recursive subroutine bort(str)
Log an error message, then either return to or abort the application program.
Definition: borts.F90:15
subroutine bort_target_unset
Clear any existing bort target.
Definition: borts.F90:180
integer function bort_target_set()
Sets a new bort target, if bort catching is enabled and such a target doesn't already exist.
Definition: borts.F90:160
recursive real *8 function pkftbv(nbits, ibit)
Compute the numerical value equivalent to the setting of bit #(ibit) within a flag table of nbits bit...
Definition: cftbvs.F90:22
recursive subroutine ufbqcd(lunit, nemo, iqcd)
Given a mnemonic associated with a category 63 Table D descriptor from an NCEP prepbufr file,...
Definition: cftbvs.F90:421
recursive subroutine ufbqcp(lunit, iqcp, nemo)
Given an event program code, which is equivalent to the Y value of a category 63 Table D descriptor f...
Definition: cftbvs.F90:493
recursive subroutine upftbv(lunit, nemo, val, mxib, ibit, nib)
Given a Table B mnemonic with flag table units and a corresponding numerical data value,...
Definition: cftbvs.F90:68
recursive subroutine getcfmng(lunit, nemoi, ivali, nemod, ivald, cmeang, lnmng, iret)
Decode the meaning of a numerical value from a code or flag table.
Definition: cftbvs.F90:229
subroutine nemtab(lun, nemo, idn, tab, iret)
Get information about a descriptor, based on a mnemonic.
Definition: fxy.F90:434
subroutine numtab(lun, idn, nemo, tab, iret)
Get information about a descriptor, based on the WMO bit-wise representation of an FXY value.
Definition: fxy.F90:359
subroutine numtbd(lun, idn, nemo, tab, iret)
Get information about a Table B or Table D descriptor, based on the WMO bit-wise representation of an...
Definition: fxy.F90:290
integer function ifxy(adsc)
Convert an FXY value from its 6 character representation to its WMO bit-wise representation.
Definition: fxy.F90:152
character *(*) function adn30(idn, ldn)
Convert an FXY value from its WMO bit-wise representation to a character string of length 5 or 6.
Definition: fxy.F90:18
integer function ireadmt(lun)
Check the most recent BUFR message that was read via a call to one of the message-reading subroutines...
recursive subroutine strnum(str, num, iret)
Decode an integer from a character string.
Definition: misc.F90:156
subroutine strsuc(str1, str2, lens)
Remove leading and trailing blanks from a character string.
Definition: misc.F90:199
Wrap C NCEPLIBS-bufr functions so they can be called from within the Fortran part of the library.
Definition: bufrlib.F90:11
Declare arrays and variables used to store DX BUFR tables internally for multiple file IDs.
character *128, dimension(:,:), allocatable tabb
Table B entries for each file ID.
Declare a variable used to indicate whether master code and flag tables should be read.
character cdmf
Flag indicating whether to include code and flag table information during reads of master BUFR tables...
recursive subroutine status(lunit, lun, il, im)
Check whether a specified Fortran logical unit number is currently connected to the NCEPLIBS-bufr sof...
subroutine parstr(str, tags, mtag, ntag, sep, limit80)
Parse a string containing one or more substrings into an array of substrings.
Definition: strings.F90:473
subroutine x48(iin4, iout8, nval)
Encode one or more 4-byte integer values as 8-byte integer values.
Definition: x4884.F90:18
subroutine x84(iin8, iout4, nval)
Encode one or more 8-byte integer values as 4-byte integer values.
Definition: x4884.F90:65