1 subroutine compack(fld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
2 !$$$ SUBPROGRAM DOCUMENTATION BLOCK
5 ! PRGMMR: Gilbert ORG: W/NP11 DATE: 2000-06-21
7 ! ABSTRACT: This subroutine packs up a data field using a complex
8 ! packing algorithm as defined in the GRIB2 documention. It
9 ! supports GRIB2 complex packing templates with or without
10 ! spatial differences (i.e. DRTs 5.2 and 5.3).
11 ! It also fills in GRIB2 Data Representation Template 5.2 or 5.3
12 ! with the appropriate values.
14 ! PROGRAM HISTORY LOG:
17 ! USAGE: CALL compack(fld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
18 ! INPUT ARGUMENT LIST:
19 ! fld() - Contains the data values to pack
20 ! ndpts - The number of data values in array fld()
21 ! idrsnum - Data Representation Template number 5.N
23 ! idrstmpl - Contains the array of values for Data Representation
25 ! (1) = Reference value - ignored on input
26 ! (2) = Binary Scale Factor
27 ! (3) = Decimal Scale Factor
30 ! (7) = Missing value management
31 ! (8) = Primary missing value
32 ! (9) = Secondary missing value
35 ! (17) = Order of Spatial Differencing ( 1 or 2 )
39 ! OUTPUT ARGUMENT LIST:
40 ! idrstmpl - Contains the array of values for Data Representation
42 ! (1) = Reference value - set by compack routine.
43 ! (2) = Binary Scale Factor - unchanged from input
44 ! (3) = Decimal Scale Factor - unchanged from input
47 ! cpack - The packed data field (character*1 array)
48 ! lcpack - length of packed field cpack().
53 ! LANGUAGE: XL Fortran 90
58 integer,intent(in) :: ndpts,idrsnum
59 real,intent(in) :: fld(ndpts)
60 character(len=1),intent(out) :: cpack(*)
61 integer,intent(inout) :: idrstmpl(*)
62 integer,intent(out) :: lcpack
66 integer,allocatable :: ifld(:)
67 integer,allocatable :: jmin(:),jmax(:),lbit(:)
68 integer,parameter :: zero=0
69 integer,allocatable :: gref(:),gwidth(:),glen(:)
70 integer :: glength,grpwidth
71 logical :: simple_alg = .false.
74 bscale=2.0**real(-idrstmpl(2))
75 dscale=10.0**real(idrstmpl(3))
77 ! Find max and min values in the data
82 if (fld(j).gt.rmax) rmax=fld(j)
83 if (fld(j).lt.rmin) rmin=fld(j)
86 ! If max and min values are not equal, pack up field.
87 ! If they are equal, we have a constant field, and the reference
88 ! value (rmin) is the value for each point in the field and
91 if (rmin.ne.rmax) then
95 allocate(gwidth(ndpts))
100 if (idrstmpl(2).eq.0) then ! No binary scaling
101 imin=nint(rmin*dscale)
102 !imax=nint(rmax*dscale)
105 ifld(j)=nint(fld(j)*dscale)-imin
107 else ! Use binary scaling factor
111 ifld(j)=nint(((fld(j)*dscale)-rmin)*bscale)
115 ! Calculate Spatial differences, if using DRS Template 5.3
117 if (idrsnum.eq.3) then ! spatial differences
118 if (idrstmpl(17).ne.1.and.idrstmpl(17).ne.2) idrstmpl(17)=2
119 if (idrstmpl(17).eq.1) then ! first order
122 ifld(j)=ifld(j)-ifld(j-1)
125 elseif (idrstmpl(17).eq.2) then ! second order
129 ifld(j)=ifld(j)-(2*ifld(j-1))+ifld(j-2)
135 ! subtract min value from spatial diff field
138 minsd=minval(ifld(isd:ndpts))
140 ifld(j)=ifld(j)-minsd
143 ! find num of bits need to store minsd and add 1 extra bit
146 temp=alog(real(abs(minsd)+1))/alog2
147 nbitsd=ceiling(temp)+1
149 ! find num of bits need to store ifld(1) ( and ifld(2)
150 ! if using 2nd order differencing )
153 if (idrstmpl(17).eq.2.and.ival2.gt.ival1) maxorig=ival2
154 temp=alog(real(maxorig+1))/alog2
155 nbitorig=ceiling(temp)+1
156 if (nbitorig.gt.nbitsd) nbitsd=nbitorig
157 ! increase number of bits to even multiple of 8 ( octet )
158 if (mod(nbitsd,8).ne.0) nbitsd=nbitsd+(8-mod(nbitsd,8))
160 ! Store extra spatial differencing info into the packed
163 if (nbitsd.ne.0) then
164 ! pack first original value
166 call g2lib_sbyte(cpack,ival1,iofst,nbitsd)
169 call g2lib_sbyte(cpack,1,iofst,1)
171 call g2lib_sbyte(cpack,iabs(ival1),iofst,nbitsd-1)
174 if (idrstmpl(17).eq.2) then
175 ! pack second original value
177 call g2lib_sbyte(cpack,ival2,iofst,nbitsd)
180 call g2lib_sbyte(cpack,1,iofst,1)
182 call g2lib_sbyte(cpack,iabs(ival2),iofst,nbitsd-1)
186 ! pack overall min of spatial differences
188 call g2lib_sbyte(cpack,minsd,iofst,nbitsd)
191 call g2lib_sbyte(cpack,1,iofst,1)
193 call g2lib_sbyte(cpack,iabs(minsd),iofst,nbitsd-1)
197 !print *,'SDp ',ival1,ival2,minsd,nbitsd
198 endif ! end of spatial diff section
200 ! Determine Groups to be used.
202 if ( simple_alg ) then
203 ! set group length to 10 : calculate number of groups
204 ! and length of last group
213 ! Use Dr. Glahn's algorithm for determining grouping.
218 maxgrps=(ndpts/minpk)+1
219 allocate(jmin(maxgrps))
220 allocate(jmax(maxgrps))
221 allocate(lbit(maxgrps))
223 call pack_gp(kfildo,ifld,ndpts,missopt,minpk,inc,miss1,miss2,
224 & jmin,jmax,lbit,glen,maxgrps,ngroups,ibit,jbit,
225 & kbit,novref,lbitref,ier)
226 !print *,'SAGier = ',ier,ibit,jbit,kbit,novref,lbitref
228 glen(ng)=glen(ng)+novref
235 ! For each group, find the group's reference value
236 ! and the number of bits needed to hold the remaining values
240 ! find max and min values of group
245 if (ifld(j).lt.gref(ng)) gref(ng)=ifld(j)
246 if (ifld(j).gt.imax) imax=ifld(j)
249 ! calc num of bits needed to hold data
250 if ( gref(ng).ne.imax ) then
251 temp=alog(real(imax-gref(ng)+1))/alog2
252 gwidth(ng)=ceiling(temp)
256 ! Subtract min from data
259 ifld(j)=ifld(j)-gref(ng)
262 ! increment fld array counter
266 ! Find max of the group references and calc num of bits needed
267 ! to pack each groups reference value, then
268 ! pack up group reference values
270 !write(77,*)'GREFS: ',(gref(j),j=1,ngroups)
271 igmax=maxval(gref(1:ngroups))
273 temp=alog(real(igmax+1))/alog2
274 nbitsgref=ceiling(temp)
275 call g2lib_sbytes(cpack,gref,iofst,nbitsgref,0,ngroups)
276 itemp=nbitsgref*ngroups
278 ! Pad last octet with Zeros, if necessary,
279 if (mod(itemp,8).ne.0) then
281 call g2lib_sbyte(cpack,zero,iofst,left)
288 ! Find max/min of the group widths and calc num of bits needed
289 ! to pack each groups width value, then
290 ! pack up group width values
292 !write(77,*)'GWIDTHS: ',(gwidth(j),j=1,ngroups)
293 iwmax=maxval(gwidth(1:ngroups))
294 ngwidthref=minval(gwidth(1:ngroups))
295 if (iwmax.ne.ngwidthref) then
296 temp=alog(real(iwmax-ngwidthref+1))/alog2
297 nbitsgwidth=ceiling(temp)
299 gwidth(i)=gwidth(i)-ngwidthref
301 call g2lib_sbytes(cpack,gwidth,iofst,nbitsgwidth,0,ngroups)
302 itemp=nbitsgwidth*ngroups
304 ! Pad last octet with Zeros, if necessary,
305 if (mod(itemp,8).ne.0) then
307 call g2lib_sbyte(cpack,zero,iofst,left)
315 ! Find max/min of the group lengths and calc num of bits needed
316 ! to pack each groups length value, then
317 ! pack up group length values
319 !write(77,*)'GLENS: ',(glen(j),j=1,ngroups)
320 ilmax=maxval(glen(1:ngroups-1))
321 nglenref=minval(glen(1:ngroups-1))
322 nglenlast=glen(ngroups)
323 if (ilmax.ne.nglenref) then
324 temp=alog(real(ilmax-nglenref+1))/alog2
325 nbitsglen=ceiling(temp)
327 glen(i)=glen(i)-nglenref
329 call g2lib_sbytes(cpack,glen,iofst,nbitsglen,0,ngroups)
330 itemp=nbitsglen*ngroups
332 ! Pad last octet with Zeros, if necessary,
333 if (mod(itemp,8).ne.0) then
335 call g2lib_sbyte(cpack,zero,iofst,left)
343 ! For each group, pack data values
345 !write(77,*)'IFLDS: ',(ifld(j),j=1,ndpts)
349 glength=glen(ng)+nglenref
350 if (ng.eq.ngroups ) glength=nglenlast
351 grpwidth=gwidth(ng)+ngwidthref
352 !write(77,*)'NGP ',ng,grpwidth,glength,gref(ng)
353 if ( grpwidth.ne.0 ) then
354 call g2lib_sbytes(cpack,ifld(n),iofst,grpwidth,0,glength)
355 iofst=iofst+(grpwidth*glength)
359 !write(77,*)'SAG ',ij,fld(ij),ifld(ij),gref(ng),bscale,rmin,dscale
363 ! Pad last octet with Zeros, if necessary,
364 if (mod(iofst,8).ne.0) then
366 call g2lib_sbyte(cpack,zero,iofst,left)
371 if ( allocated(ifld) ) deallocate(ifld)
372 if ( allocated(gref) ) deallocate(gref)
373 if ( allocated(gwidth) ) deallocate(gwidth)
374 if ( allocated(glen) ) deallocate(glen)
375 else ! Constant field ( max = min )
383 ! Fill in ref value and number of bits in Template 5.2
385 call mkieee(rmin,ref,1) ! ensure reference value is IEEE format
386 ! call g2lib_gbyte(ref,idrstmpl(1),0,32)
387 iref=transfer(ref,iref)
389 idrstmpl(4)=nbitsgref
390 idrstmpl(5)=0 ! original data were reals
391 idrstmpl(6)=1 ! general group splitting
392 idrstmpl(7)=0 ! No internal missing values
393 idrstmpl(8)=0 ! Primary missing value
394 idrstmpl(9)=0 ! secondary missing value
395 idrstmpl(10)=ngroups ! Number of groups
396 idrstmpl(11)=ngwidthref ! reference for group widths
397 idrstmpl(12)=nbitsgwidth ! num bits used for group widths
398 idrstmpl(13)=nglenref ! Reference for group lengths
399 idrstmpl(14)=1 ! length increment for group lengths
400 idrstmpl(15)=nglenlast ! True length of last group
401 idrstmpl(16)=nbitsglen ! num bits used for group lengths
402 if (idrsnum.eq.3) then
403 idrstmpl(18)=nbitsd/8 ! num bits used for extra spatial
404 ! differencing values