NCEPLIBS-g2  3.4.7
addfield.f
Go to the documentation of this file.
1 
5 
72  subroutine addfield(cgrib,lcgrib,ipdsnum,ipdstmpl,ipdstmplen,
73  & coordlist,numcoord,idrsnum,idrstmpl,
74  & idrstmplen,fld,ngrdpts,ibmap,bmap,ierr)
75  use pdstemplates
76  use drstemplates
77  implicit none
78 
79  logical :: match
80  character(len=1),intent(inout) :: cgrib(lcgrib)
81  integer,intent(in) :: ipdsnum,ipdstmpl(*)
82  integer,intent(in) :: idrsnum,numcoord,ipdstmplen,idrstmplen
83  integer,intent(in) :: lcgrib,ngrdpts,ibmap
84  real,intent(in) :: coordlist(numcoord)
85  real(kind = 4) :: coordlist_4(numcoord)
86  real,target,intent(in) :: fld(ngrdpts)
87  integer,intent(out) :: ierr
88  integer,intent(inout) :: idrstmpl(*)
89  logical*1,intent(in) :: bmap(ngrdpts)
90 
91  character(len=4),parameter :: grib='GRIB',c7777='7777'
92  character(len=4):: ctemp
93  character(len=1),allocatable :: cpack(:)
94  real,pointer,dimension(:) :: pfld
95  real(4) :: coordieee(numcoord),re00
96  integer(4) :: ire00,allones
97  integer :: mappds(ipdstmplen),intbmap(ngrdpts),mapdrs(idrstmplen)
98  integer,parameter :: zero=0,one=1,four=4,five=5,six=6,seven=7
99  integer,parameter :: minsize=50000
100  integer iofst,ibeg,lencurr,len,mappdslen,mapdrslen,lpos3
101  integer width,height,ndpts
102  integer lensec3,lensec4,lensec5,lensec6,lensec7
103  logical issec3,needext,isprevbmap
104  integer :: nbits, newlen, nsize, lcpack, left
105  integer :: ibmprev, ilen, ioctet, iscan, isecnum, itemp
106  integer :: i, jj, kk, mm
107  integer :: iret, istat
108 
109  allones = int(z'FFFFFFFF')
110  ierr=0
111 
112 ! Check to see if beginning of GRIB message exists
113  match=.true.
114  do i=1,4
115  if(cgrib(i) /= grib(i:i)) then
116  match=.false.
117  endif
118  enddo
119  if (.not. match) then
120  print *,'addfield: GRIB not found in given message.'
121  print *,'addfield: Call to routine gribcreate required',
122  & ' to initialize GRIB messge.'
123  ierr=1
124  return
125  endif
126 
127 ! Get current length of GRIB message
128  call g2_gbytec(cgrib,lencurr,96,32)
129 
130 ! Check to see if GRIB message is already complete
131  ctemp=cgrib(lencurr-3)//cgrib(lencurr-2)//cgrib(lencurr-1)
132  & //cgrib(lencurr)
133  if (ctemp.eq.c7777) then
134  print *,'addfield: GRIB message already complete. Cannot',
135  & ' add new section.'
136  ierr=2
137  return
138  endif
139 
140 ! Loop through all current sections of the GRIB message to
141 ! find the last section number.
142  issec3=.false.
143  isprevbmap=.false.
144  len=16 ! length of Section 0
145  do
146  ! Get number and length of next section
147  iofst=len*8
148  call g2_gbytec(cgrib,ilen,iofst,32)
149  iofst=iofst+32
150  call g2_gbytec(cgrib,isecnum,iofst,8)
151  iofst=iofst+8
152  ! Check if previous Section 3 exists and save location of
153  ! the section 3 in case needed later.
154  if (isecnum.eq.3) then
155  issec3=.true.
156  lpos3=len+1
157  lensec3=ilen
158  endif
159  ! Check if a previous defined bitmap exists
160  if (isecnum.eq.6) then
161  call g2_gbytec(cgrib,ibmprev,iofst,8)
162  iofst=iofst+8
163  if ((ibmprev.ge.0).and.(ibmprev.le.253)) isprevbmap=.true.
164  endif
165  len=len+ilen
166  ! Exit loop if last section reached
167  if (len.eq.lencurr) exit
168  ! If byte count for each section does not match current
169  ! total length, then there is a problem.
170  if (len.gt.lencurr) then
171  print *,'addfield: Section byte counts don''t add to total.'
172  print *,'addfield: Sum of section byte counts = ',len
173  print *,'addfield: Total byte count in Section 0 = ',lencurr
174  ierr=3
175  return
176  endif
177  enddo
178 
179 ! Sections 4 through 7 can only be added after section 3 or 7.
180  if ((isecnum.ne.3) .and. (isecnum.ne.7)) then
181  print *,'addfield: Sections 4-7 can only be added after',
182  & ' Section 3 or 7.'
183  print *,'addfield: Section ',isecnum,' was the last found in',
184  & ' given GRIB message.'
185  ierr=4
186  return
187 
188 ! Sections 4 through 7 can only be added if section 3 was previously defined.
189  elseif (.not.issec3) then
190  print *,'addfield: Sections 4-7 can only be added if Section',
191  & ' 3 was previously included.'
192  print *,'addfield: Section 3 was not found in',
193  & ' given GRIB message.'
194  print *,'addfield: Call to routine addgrid required',
195  & ' to specify Grid definition.'
196  ierr=6
197  return
198  endif
199 
200 ! Add Section 4 - Product Definition Section
201  ibeg=lencurr*8 ! Calculate offset for beginning of section 4
202  iofst=ibeg+32 ! leave space for length of section
203  call g2_sbytec(cgrib,four,iofst,8) ! Store section number (4)
204  iofst=iofst+8
205  call g2_sbytec(cgrib,numcoord,iofst,16) ! Store num of coordinate values
206  iofst=iofst+16
207  call g2_sbytec(cgrib,ipdsnum,iofst,16) ! Store Prod Def Template num.
208  iofst=iofst+16
209 
210  ! Get Product Definition Template
211  call getpdstemplate(ipdsnum,mappdslen,mappds,needext,iret)
212  if (iret.ne.0) then
213  ierr=5
214  return
215  endif
216 
217  ! Extend the Product Definition Template, if necessary.
218  ! The number of values in a specific template may vary
219  ! depending on data specified in the "static" part of the
220  ! template.
221  if (needext) then
222  call extpdstemplate(ipdsnum,ipdstmpl,mappdslen,mappds)
223  endif
224 
225  ! Pack up each input value in array ipdstmpl into the
226  ! the appropriate number of octets, which are specified in
227  ! corresponding entries in array mappds.
228  do i=1,mappdslen
229  nbits=iabs(mappds(i))*8
230  if ((mappds(i).ge.0).or.(ipdstmpl(i).ge.0)) then
231  call g2_sbytec(cgrib,ipdstmpl(i),iofst,nbits)
232  else
233  call g2_sbytec(cgrib,one,iofst,1)
234  call g2_sbytec(cgrib,iabs(ipdstmpl(i)),iofst+1,nbits-1)
235  endif
236  iofst=iofst+nbits
237  enddo
238 
239  ! Add Optional list of vertical coordinate values
240  ! after the Product Definition Template, if necessary.
241  if (numcoord .ne. 0) then
242  do i = 1, numcoord
243  coordlist_4(i) = real(coordlist(i), 4)
244  end do
245  call mkieee(coordlist_4, coordieee, numcoord)
246  call g2_sbytesc(cgrib,coordieee,iofst,32,0,numcoord)
247  iofst=iofst+(32*numcoord)
248  endif
249 
250  ! Calculate length of section 4 and store it in octets
251  ! 1-4 of section 4.
252  lensec4=(iofst-ibeg)/8
253  call g2_sbytec(cgrib,lensec4,ibeg,32)
254 
255 ! Pack Data using appropriate algorithm
256 
257  ! Get Data Representation Template
258  call getdrstemplate(idrsnum,mapdrslen,mapdrs,needext,iret)
259  if (iret.ne.0) then
260  ierr=5
261  return
262  endif
263 
264  ! contract data field, removing data at invalid grid points,
265  ! if bit-map is provided with field.
266  if (ibmap.eq.0 .OR. ibmap.eq.254) then
267  allocate(pfld(max(2,ngrdpts)))
268  ndpts=0;
269  do jj=1,ngrdpts
270  intbmap(jj)=0
271  if (bmap(jj)) then
272  intbmap(jj)=1
273  ndpts=ndpts+1
274  pfld(ndpts)=fld(jj);
275  endif
276  enddo
277  if(ndpts==0 .and. ngrdpts>0) then
278  pfld(1)=0
279  endif
280  else
281  ndpts=ngrdpts;
282  pfld=>fld;
283  endif
284  lcpack=0
285  nsize=ndpts*4
286  if (nsize .lt. minsize) nsize=minsize
287  allocate(cpack(nsize),stat=istat)
288  if (idrsnum.eq.0) then ! Simple Packing
289  call simpack(pfld,ndpts,idrstmpl,cpack,lcpack)
290  elseif (idrsnum.eq.2.or.idrsnum.eq.3) then ! Complex Packing
291  call cmplxpack(pfld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
292  elseif (idrsnum.eq.50) then ! Sperical Harmonic Simple Packing
293  call simpack(pfld(2),ndpts-1,idrstmpl,cpack,lcpack)
294  call mkieee(real(pfld(1)),re00,1) ! ensure RE(0,0) value is IEEE format
295  !call g2_gbytec(re00,idrstmpl(5),0,32)
296  ire00=transfer(re00,ire00)
297  idrstmpl(5)=ire00
298  elseif (idrsnum.eq.51) then ! Sperical Harmonic Complex Packing
299  call getpoly(cgrib(lpos3),lensec3,jj,kk,mm)
300  if (jj.ne.0 .AND. kk.ne.0 .AND. mm.ne.0) then
301  call specpack(pfld,ndpts,jj,kk,mm,idrstmpl,cpack,lcpack)
302  else
303  print *,'addfield: Cannot pack DRT 5.51.'
304  ierr=9
305  return
306  endif
307 
308  elseif (idrsnum.eq.40 .OR. idrsnum.eq.40000) then ! JPEG2000 encoding
309  if (ibmap.eq.255) then
310  call getdim(cgrib(lpos3),lensec3,width,height,iscan)
311  if (width.eq.0 .OR. height.eq.0) then
312  width=ndpts
313  height=1
314  elseif (width.eq.allones .OR. height.eq.allones) then
315  width=ndpts
316  height=1
317  elseif (ibits(iscan,5,1) .eq. 1) then ! Scanning mode: bit 3
318  itemp=width
319  width=height
320  height=itemp
321  endif
322  else
323  width=ndpts
324  height=1
325  endif
326  if(width<1 .or. height<1) then
327  ! Special case: bitmask off everywhere.
328  write(0,*) 'Warning: bitmask off everywhere.'
329  write(0,*) ' Pretend one point in jpcpack to avoid crash.'
330  width=1
331  height=1
332  endif
333  lcpack=nsize
334  !print *,'w,h=',width,height
335  call jpcpack(pfld,width,height,idrstmpl,cpack,lcpack)
336 
337  elseif (idrsnum.eq.41 .OR. idrsnum.eq.40010) then ! PNG encoding
338  if (ibmap.eq.255) then
339  call getdim(cgrib(lpos3),lensec3,width,height,iscan)
340  if (width.eq.0 .OR. height.eq.0) then
341  width=ndpts
342  height=1
343  elseif (width.eq.allones .OR. height.eq.allones) then
344  width=ndpts
345  height=1
346  elseif (ibits(iscan,5,1) .eq. 1) then ! Scanning mode: bit 3
347  itemp=width
348  width=height
349  height=itemp
350  endif
351  else
352  width=ndpts
353  height=1
354  endif
355  !print *,'png size ',width,height
356  call pngpack(pfld,width,height,idrstmpl,cpack,lcpack)
357  !print *,'png packed'
358  else
359  print *,'addfield: Data Representation Template 5.',idrsnum,
360  * ' not yet implemented.'
361  ierr=7
362  return
363  endif
364  if (ibmap.eq.0 .OR. ibmap.eq.254) then
365  deallocate(pfld)
366  endif
367  if (lcpack .lt. 0) then
368  if(allocated(cpack))deallocate(cpack)
369  ierr=10
370  return
371  endif
372 
373 ! Add Section 5 - Data Representation Section
374  ibeg=iofst ! Calculate offset for beginning of section 5
375  iofst=ibeg+32 ! leave space for length of section
376  call g2_sbytec(cgrib,five,iofst,8) ! Store section number (5)
377  iofst=iofst+8
378  call g2_sbytec(cgrib,ndpts,iofst,32) ! Store num of actual data points
379  iofst=iofst+32
380  call g2_sbytec(cgrib,idrsnum,iofst,16) ! Store Data Repr. Template num.
381  iofst=iofst+16
382 
383  ! Pack up each input value in array idrstmpl into the
384  ! the appropriate number of octets, which are specified in
385  ! corresponding entries in array mapdrs.
386  do i=1,mapdrslen
387  nbits=iabs(mapdrs(i))*8
388  if ((mapdrs(i).ge.0).or.(idrstmpl(i).ge.0)) then
389  call g2_sbytec(cgrib,idrstmpl(i),iofst,nbits)
390  else
391  call g2_sbytec(cgrib,one,iofst,1)
392  call g2_sbytec(cgrib,iabs(idrstmpl(i)),iofst+1,nbits-1)
393  endif
394  iofst=iofst+nbits
395  enddo
396 
397  ! Calculate length of section 5 and store it in octets
398  ! 1-4 of section 5.
399  lensec5=(iofst-ibeg)/8
400  call g2_sbytec(cgrib,lensec5,ibeg,32)
401 
402 ! Add Section 6 - Bit-Map Section
403  ibeg=iofst ! Calculate offset for beginning of section 6
404  iofst=ibeg+32 ! leave space for length of section
405  call g2_sbytec(cgrib,six,iofst,8) ! Store section number (6)
406  iofst=iofst+8
407  call g2_sbytec(cgrib,ibmap,iofst,8) ! Store Bit Map indicator
408  iofst=iofst+8
409 
410  ! Store bitmap, if supplied
411  if (ibmap.eq.0) then
412  call g2_sbytesc(cgrib,intbmap,iofst,1,0,ngrdpts) ! Store BitMap
413  iofst=iofst+ngrdpts
414  endif
415 
416  ! If specifying a previously defined bit-map, make sure
417  ! one already exists in the current GRIB message.
418  if ((ibmap.eq.254).and.(.not.isprevbmap)) then
419  print *,'addfield: Requested previously defined bitmap, ',
420  & ' but one does not exist in the current GRIB message.'
421  ierr=8
422  return
423  endif
424 
425  ! Calculate length of section 6 and store it in octets
426  ! 1-4 of section 6. Pad to end of octect, if necessary.
427  left=8-mod(iofst,8)
428  if (left.ne.8) then
429  call g2_sbytec(cgrib,zero,iofst,left) ! Pad with zeros to fill Octet
430  iofst=iofst+left
431  endif
432  lensec6=(iofst-ibeg)/8
433  call g2_sbytec(cgrib,lensec6,ibeg,32)
434 
435 ! Add Section 7 - Data Section
436  ibeg=iofst ! Calculate offset for beginning of section 7
437  iofst=ibeg+32 ! leave space for length of section
438  call g2_sbytec(cgrib,seven,iofst,8) ! Store section number (7)
439  iofst=iofst+8
440  ! Store Packed Binary Data values, if non-constant field
441  if (lcpack.ne.0) then
442  ioctet=iofst/8
443  cgrib(ioctet+1:ioctet+lcpack)=cpack(1:lcpack)
444  iofst=iofst+(8*lcpack)
445  endif
446 
447  ! Calculate length of section 7 and store it in octets
448  ! 1-4 of section 7.
449  lensec7=(iofst-ibeg)/8
450  call g2_sbytec(cgrib,lensec7,ibeg,32)
451 
452  if(allocated(cpack) )deallocate(cpack)
453 
454 ! Update current byte total of message in Section 0
455  newlen=lencurr+lensec4+lensec5+lensec6+lensec7
456  call g2_sbytec(cgrib,newlen,96,32)
457 
458  return
459  end
subroutine addfield(cgrib, lcgrib, ipdsnum, ipdstmpl, ipdstmplen, coordlist, numcoord, idrsnum, idrstmpl, idrstmplen, fld, ngrdpts, ibmap, bmap, ierr)
Pack up Sections 4 through 7 for a given field and add them to a GRIB2 message.
Definition: addfield.f:75
subroutine cmplxpack(fld, ndpts, idrsnum, idrstmpl, cpack, lcpack)
Pack up a data field using a complex packing algorithm.
Definition: cmplxpack.f:38
subroutine g2_gbytec(in, iout, iskip, nbits)
Extract arbitrary size values from a packed bit string, right justifying each value in the unpacked a...
Definition: g2_gbytesc.F90:20
subroutine g2_sbytec(out, in, iskip, nbits)
Put arbitrary size values into a packed bit string, taking the low order bits from each value in the ...
Definition: g2_gbytesc.F90:42
subroutine g2_sbytesc(out, in, iskip, nbits, nskip, n)
Put arbitrary size values into a packed bit string, taking the low order bits from each value in the ...
Definition: g2_gbytesc.F90:120
subroutine getdim(csec3, lcsec3, width, height, iscan)
This subroutine returns the dimensions and scanning mode of a grid definition packed in GRIB2 Grid De...
Definition: getdim.f:22
subroutine getpoly(csec3, lcsec3, jj, kk, mm)
Return the J, K, and M pentagonal resolution parameters specified in a GRIB2 Grid Definition Section ...
Definition: getpoly.f:21
subroutine jpcpack(fld, width, height, idrstmpl, cpack, lcpack)
Pack a data field into a JPEG2000 code stream.
Definition: jpcpack.F90:32
subroutine mkieee(a, rieee, num)
Copy an array of real to an array of 32-bit IEEE floating points.
Definition: mkieee.F90:14
Handles Data Representation Templates used in Section 5.
subroutine getdrstemplate(number, nummap, map, needext, iret)
Return DRS template information for a specified Data Representation Template.
Information on all GRIB2 Product Definition Templates used in Section 4 - the Product Definition Sect...
subroutine extpdstemplate(number, list, nummap, map)
This subroutine generates the remaining octet map for a given Product Definition Template,...
subroutine getpdstemplate(number, nummap, map, needext, iret)
This subroutine returns PDS template information for a specified Product Definition Template.
subroutine pngpack(fld, width, height, idrstmpl, cpack, lcpack)
This subroutine packs up a data field into PNG image format.
Definition: pngpack.F90:29
subroutine simpack(fld, ndpts, idrstmpl, cpack, lcpack)
Pack up a data field using a simple packing algorithm as defined in the GRIB2 documention.
Definition: simpack.f:26
subroutine specpack(fld, ndpts, JJ, KK, MM, idrstmpl, cpack, lcpack)
This subroutine packs a spectral data field using the complex packing algorithm for spherical harmoni...
Definition: specpack.F90:22