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 sbyte
(cpack
,ival1
,iofst
,nbitsd
)
169 call sbyte
(cpack
,1,iofst
,1)
171 call sbyte
(cpack
,iabs
(ival1
),iofst
,nbitsd
-1)
174 if (idrstmpl
(17).eq
.2) then
175 ! pack second original value
177 call sbyte
(cpack
,ival2
,iofst
,nbitsd
)
180 call sbyte
(cpack
,1,iofst
,1)
182 call sbyte
(cpack
,iabs
(ival2
),iofst
,nbitsd
-1)
186 ! pack overall min of spatial differences
188 call sbyte
(cpack
,minsd
,iofst
,nbitsd
)
191 call sbyte
(cpack
,1,iofst
,1)
193 call 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 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 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 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 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 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 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 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 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 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