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
:
16 ! 2011-10-24 Boi Vuong Added variable rmin4
for 4 byte float
18 ! USAGE
: CALL compack
(fld
,ndpts
,idrsnum
,idrstmpl
,cpack
,lcpack
)
19 ! INPUT ARGUMENT LIST
:
20 ! fld
() - Contains the data values
to pack
21 ! ndpts
- The number of data values in array fld
()
22 ! idrsnum
- Data Representation Template number
5.N
24 ! idrstmpl
- Contains the array of values
for Data Representation
26 ! (1) = Reference value
- ignored on input
27 ! (2) = Binary Scale Factor
28 ! (3) = Decimal Scale Factor
31 ! (7) = Missing value management
32 ! (8) = Primary missing value
33 ! (9) = Secondary missing value
36 ! (17) = Order of Spatial Differencing
( 1 or
2 )
40 ! OUTPUT ARGUMENT LIST
:
41 ! idrstmpl
- Contains the array of values
for Data Representation
43 ! (1) = Reference value
- set by compack routine
.
44 ! (2) = Binary Scale Factor
- unchanged from input
45 ! (3) = Decimal Scale Factor
- unchanged from input
48 ! cpack
- The packed data field
(character*1 array
)
49 ! lcpack
- length of packed field cpack
().
54 ! LANGUAGE
: XL Fortran
90
60 integer,intent
(in
) :: ndpts
,idrsnum
61 real,intent
(in
) :: fld
(ndpts
)
62 character(len
=1),intent
(out
) :: cpack
(*)
63 integer,intent
(inout
) :: idrstmpl
(*)
64 integer,intent
(out
) :: lcpack
67 integer :: j
,iofst
,imin
,ival1
,ival2
,minsd
,nbitsd
,n
68 integer :: igmax
,nbitsgref
,left
,iwmax
,i
,ilmax
,kk
,ij
69 integer :: ngwidthref
,nbitsgwidth
,nglenref
,nglenlast
70 integer :: maxorig
,nbitorig
,isd
,ngroups
,itemp
,minpk
71 integer :: kfildo
,inc
,maxgrps
,missopt
,miss1
,miss2
,lg
72 integer :: ibit
,jbit
,kbit
,novref
,lbitref
,ier
,ng
,imax
78 integer,allocatable
:: ifld
(:)
79 integer,allocatable
:: jmin
(:),jmax
(:),lbit
(:)
80 integer,parameter :: zero
=0
81 integer,allocatable
:: gref
(:),gwidth
(:),glen
(:)
82 integer :: glength
,grpwidth
87 bscale
=2.0**real(-idrstmpl
(2))
88 dscale
=10.0**real(idrstmpl
(3))
90 ! Find max and min values in the data
100 if (fld
(j
).gt
.rmax
) rmax
=fld
(j
)
101 if (fld
(j
).lt
.rmin
) rmin
=fld
(j
)
104 ! If max and min values are not equal
, pack up field
.
105 ! If they are equal
, we have a constant field
, and the reference
106 ! value
(rmin
) is the value
for each point in the field and
109 multival
: if (rmin
.ne
.rmax
) then
111 allocate
(ifld
(ndpts
))
112 allocate
(gref
(ndpts
))
113 allocate
(gwidth
(ndpts
))
114 allocate
(glen
(ndpts
))
116 ! Scale original data
118 if (idrstmpl
(2).eq
.0) then ! No binary scaling
119 imin
=nint
(rmin*dscale
)
120 !imax
=nint
(rmax*dscale
)
123 ifld
(j
)=max
(0,nint
(fld
(j
)*dscale
)-imin
)
125 else ! Use binary scaling factor
129 ifld
(j
)=max
(0,nint
(((fld
(j
)*dscale
)-rmin
)*bscale
))
133 ! Calculate Spatial differences
, if using DRS Template
5.3
135 alg3
: if (idrsnum
.eq
.3) then ! spatial differences
136 if (idrstmpl
(17).ne
.1.and
.idrstmpl
(17).ne
.2) idrstmpl
(17)=2
137 if (idrstmpl
(17).eq
.1) then ! first order
140 print
*,'G2: negative ival1',ival1
144 ifld
(j
)=ifld
(j
)-ifld
(j
-1)
147 elseif
(idrstmpl
(17).eq
.2) then ! second order
151 print
*,'G2: negative ival1',ival1
155 print
*,'G2: negative ival2',ival2
159 ifld
(j
)=ifld
(j
)-(2*ifld
(j
-1))+ifld
(j
-2)
165 ! subtract min value from spatial diff field
168 minsd
=minval
(ifld
(isd
:ndpts
))
170 ifld
(j
)=ifld
(j
)-minsd
173 ! find num of bits need
to store minsd and add
1 extra bit
176 nbitsd
=i1log2
(abs
(minsd
))+1
178 ! find num of bits need
to store ifld
(1) ( and ifld
(2)
179 ! if using
2nd order differencing
)
182 if (idrstmpl
(17).eq
.2.and
.ival2
.gt
.ival1
) maxorig
=ival2
183 nbitorig
=i1log2
(maxorig
)+1
184 if (nbitorig
.gt
.nbitsd
) nbitsd
=nbitorig
185 ! increase number of bits
to even multiple of
8 ( octet
)
186 if (mod
(nbitsd
,8).ne
.0) nbitsd
=nbitsd
+(8-mod
(nbitsd
,8))
188 ! Store extra spatial differencing info into the packed
191 if (nbitsd
.ne
.0) then
192 ! pack first original value
194 call sbyte
(cpack
,ival1
,iofst
,nbitsd
)
197 call sbyte
(cpack
,1,iofst
,1)
199 call sbyte
(cpack
,iabs
(ival1
),iofst
,nbitsd
-1)
202 if (idrstmpl
(17).eq
.2) then
203 ! pack second original value
205 call sbyte
(cpack
,ival2
,iofst
,nbitsd
)
208 call sbyte
(cpack
,1,iofst
,1)
210 call sbyte
(cpack
,iabs
(ival2
),iofst
,nbitsd
-1)
214 ! pack overall min of spatial differences
216 call sbyte
(cpack
,minsd
,iofst
,nbitsd
)
219 call sbyte
(cpack
,1,iofst
,1)
221 call sbyte
(cpack
,iabs
(minsd
),iofst
,nbitsd
-1)
225 !print
*,'SDp ',ival1
,ival2
,minsd
,nbitsd
226 endif alg3
! end of spatial diff section
228 ! Determine Groups
to be used
.
230 simplealg
: if ( simple_alg
) then
231 ! set group length
to 10 : calculate number of groups
232 ! and length of last group
233 ! print
*,'G2: use simple algorithm'
242 ! Use Dr
. Glahn
's algorithm for determining grouping.
247 maxgrps=((ndpts+minpk-1)/minpk)
248 allocate(jmin(maxgrps))
249 allocate(jmax(maxgrps))
250 allocate(lbit(maxgrps))
252 call pack_gp(kfildo,ifld,ndpts,missopt,minpk,inc,miss1,miss2,
253 & jmin,jmax,lbit,glen,maxgrps,ngroups,ibit,jbit,
254 & kbit,novref,lbitref,ier)
256 ! Dr. Glahn's algorithm failed
; use simple packing method instead
.
257 1099 format('G2: fall back to simple algorithm (glahn ier=',I0
,&
267 elseif
(ngroups
<1) then
268 ! Dr
. Glahn
's algorithm failed; use simple packing method instead.
269 print *,'Glahn algorithm failed
; use simple packing
'
278 !print *,'SAGier
= ',ier,ibit,jbit,kbit,novref,lbitref
280 glen(ng)=glen(ng)+novref
288 ! For each group, find the group's reference value
289 ! and the number of bits needed
to hold the remaining values
293 ! find max and min values of group
298 if (ifld
(j
).lt
.gref
(ng
)) gref
(ng
)=ifld
(j
)
299 if (ifld
(j
).gt
.imax
) imax
=ifld
(j
)
302 ! calc num of bits needed
to hold data
303 if ( gref
(ng
).ne
.imax
) then
304 gwidth
(ng
)=i1log2
(imax
-gref
(ng
))
308 ! Subtract min from data
311 ifld
(j
)=ifld
(j
)-gref
(ng
)
314 ! increment fld array counter
318 ! Find max of the group references and calc num of bits needed
319 ! to pack each groups reference value
, then
320 ! pack up group reference values
322 !write(77,*)'GREFS: ',(gref
(j
),j
=1,ngroups
)
323 igmax
=maxval
(gref
(1:ngroups
))
325 nbitsgref
=i1log2
(igmax
)
326 call sbytes
(cpack
,gref
,iofst
,nbitsgref
,0,ngroups
)
327 itemp
=nbitsgref*ngroups
329 if (mod
(itemp
,8).ne
.0) then
331 call sbyte
(cpack
,zero
,iofst
,left
)
338 ! Find max
/min of the group widths and calc num of bits needed
339 ! to pack each groups width value
, then
340 ! pack up group width values
342 !write(77,*)'GWIDTHS: ',(gwidth
(j
),j
=1,ngroups
)
343 iwmax
=maxval
(gwidth
(1:ngroups
))
344 ngwidthref
=minval
(gwidth
(1:ngroups
))
345 if (iwmax
.ne
.ngwidthref
) then
346 nbitsgwidth
=i1log2
(iwmax
-ngwidthref
)
348 gwidth
(i
)=gwidth
(i
)-ngwidthref
350 write(0,*) 'i,gw,ngw=',i
,gwidth
(i
),ngwidthref
354 call sbytes
(cpack
,gwidth
,iofst
,nbitsgwidth
,0,ngroups
)
355 itemp
=nbitsgwidth*ngroups
357 ! Pad last octet with Zeros
, if necessary
,
358 if (mod
(itemp
,8).ne
.0) then
360 call sbyte
(cpack
,zero
,iofst
,left
)
368 ! Find max
/min of the group lengths and calc num of bits needed
369 ! to pack each groups length value
, then
370 ! pack up group length values
372 !write(77,*)'GLENS: ',(glen
(j
),j
=1,ngroups
)
373 ilmax
=maxval
(glen
(1:ngroups
-1))
374 nglenref
=minval
(glen
(1:ngroups
-1))
375 nglenlast
=glen
(ngroups
)
376 if (ilmax
.ne
.nglenref
) then
377 nbitsglen
=i1log2
(ilmax
-nglenref
)
379 glen
(i
)=glen
(i
)-nglenref
381 write(0,*) 'i,glen(i) = ',i
,glen
(i
)
385 call sbytes
(cpack
,glen
,iofst
,nbitsglen
,0,ngroups
)
386 itemp
=nbitsglen*ngroups
388 ! Pad last octet with Zeros
, if necessary
,
389 if (mod
(itemp
,8).ne
.0) then
391 call sbyte
(cpack
,zero
,iofst
,left
)
399 ! For each group
, pack data values
401 !write(77,*)'IFLDS: ',(ifld
(j
),j
=1,ndpts
)
405 glength
=glen
(ng
)+nglenref
406 if (ng
.eq
.ngroups
) glength
=nglenlast
407 grpwidth
=gwidth
(ng
)+ngwidthref
408 !write(77,*)'NGP ',ng
,grpwidth
,glength
,gref
(ng
)
409 if ( grpwidth
.ne
.0 ) then
410 call sbytes
(cpack
,ifld
(n
),iofst
,grpwidth
,0,glength
)
411 iofst
=iofst
+(grpwidth*glength
)
415 !write(77,*)'SAG ',ij
,fld
(ij
),ifld
(ij
),gref
(ng
),bscale
,rmin
,dscale
419 ! Pad last octet with Zeros
, if necessary
,
420 if (mod
(iofst
,8).ne
.0) then
422 call sbyte
(cpack
,zero
,iofst
,left
)
427 if ( allocated
(ifld
) ) deallocate
(ifld
)
428 if ( allocated
(gref
) ) deallocate
(gref
)
429 if ( allocated
(gwidth
) ) deallocate
(gwidth
)
430 if ( allocated
(glen
) ) deallocate
(glen
)
431 else ! Constant field
( max
= min
)
444 ! Fill in ref value and number of bits in Template
5.2
447 call mkieee
(rmin4
,ref
,1) ! ensure reference value is IEEE
format
448 ! call gbyte
(ref
,idrstmpl
(1),0,32)
449 iref
=transfer
(ref
,iref
)
451 idrstmpl
(4)=nbitsgref
452 idrstmpl
(5)=0 ! original data were reals
453 idrstmpl
(6)=1 ! general group splitting
454 idrstmpl
(7)=0 ! No internal missing values
455 idrstmpl
(8)=0 ! Primary missing value
456 idrstmpl
(9)=0 ! secondary missing value
457 idrstmpl
(10)=ngroups
! Number of groups
458 idrstmpl
(11)=ngwidthref
! reference
for group widths
459 idrstmpl
(12)=nbitsgwidth
! num bits used
for group widths
460 idrstmpl
(13)=nglenref
! Reference
for group lengths
461 idrstmpl
(14)=1 ! length increment
for group lengths
462 idrstmpl
(15)=nglenlast
! True length of last group
463 idrstmpl
(16)=nbitsglen
! num bits used
for group lengths
464 if (idrsnum
.eq
.3) then
465 idrstmpl
(18)=nbitsd
/8 ! num bits used
for extra spatial
466 ! differencing values