SURFEX v8.1
General documentation of Surfex
compress_field.f90
Go to the documentation of this file.
1 !-----------------------------------------------------------------
2 !--------------- special set of characters for RCS information
3 !-----------------------------------------------------------------
4 ! $Source: /home/cvsroot/mesonh/libtools/lib/COMPRESS/src/compress.f90,v $ $Revision: 1.1.2.1 $ $Date: 2007/03/02 13:15:26 $
5 !-----------------------------------------------------------------
6 SUBROUTINE compress_field(XTAB,KX,KY,KNBTOT,KNBUSE)
9 
10 #ifdef NAGf95
11 use,INTRINSIC :: ieee_arithmetic
12 #endif
13 
14 IMPLICIT NONE
15 
16 REAL,PARAMETER :: PPFLOATMIN = 2.0**(-126)
17 
18 INTEGER, INTENT(IN) :: KX,KY
19 !INTEGER, INTENT(IN) :: KNBLEV
20 INTEGER, INTENT(IN) :: KNBTOT
21 REAL(KIND=8),DIMENSION(KNBTOT),INTENT(INOUT) :: XTAB
22 
23 INTEGER, INTENT(OUT) :: KNBUSE
24 
25 INTEGER :: INBLEV
26 INTEGER,DIMENSION(:), ALLOCATABLE :: ITAB
27 REAL :: XMIN,XMAX
28 TYPE(sop_t) :: SOPRES
29 INTEGER :: IND1, IND2
30 INTEGER :: GELT,IBE
31 INTEGER :: ILEVNBELT
32 INTEGER :: NBITCOD
33 INTEGER :: II, JI, JJ
34 INTEGER :: BITOFFSET
35 INTEGER :: GRPIDX,GRPOFF,IDXSAVE,OFFSAVE
36 INTEGER :: nbgroupmod
37 INTEGER :: IEXTCOD
38  CHARACTER(LEN=8),PARAMETER :: KEYWORD='COMPRESS'
39 REAL,DIMENSION(KNBTOT) :: XWORKTAB
40 LOGICAL :: LUPREAL,LNAN
41 #ifndef NAGf95
42 LOGICAL, EXTERNAL :: IEEE_IS_NAN
43 #endif
44 
45 ilevnbelt = kx*ky
46 lupreal = .false.
47 lnan = .false.
48 
49 ! Check for NAN and change Upper and Lower bound according to 32bits real limits.
50 DO ji=1,knbtot
51  IF (ieee_is_nan(xtab(ji))) THEN
52  xtab(ji)=0.
53  lnan = .true.
54  ELSE IF (abs(xtab(ji)) > huge(1.0_4)) THEN
55  xtab(ji) = sign(REAL(HUGE(1.0_4)/1.1,8),XTAB(ji))
56  lupreal = .true.
57  ELSEIF (abs(xtab(ji)) < tiny(1.0_4)) THEN
58  xtab(ji) = 0.
59  END IF
60 END DO
61 
62 xmin=minval(xtab)
63 xmax=maxval(xtab)
64 print *,'MINVAL,MAXVAL= ',xmin,xmax
65 IF (lnan) print *,"==================> NAN values DETECTED : set to 0.0"
66 IF (lupreal) print *,"==================> OVERFLOW values DETECTED : set to ",huge(1.0_4)/1.1
67 
68 ! Convert 64 bits real to 32 bits real
69 xworktab(:) = xtab(:)
70 !
71 ! BEWARE : Now XTAB is overwritten.
72 ! XWORKTAB contains the 32 bits floating point data.
73 !
74  CALL set_fillidx(0,0)
75 ! store 8 characters header string in buffer
76 DO ii=1,len(keyword)
77  CALL fill_bbuff(xtab,8,ichar(keyword(ii:ii)))
78 END DO
79 
80 ! is whole array XTAB64 a constant field ?
81 
82 IF (xmin == xmax) THEN
83  print *,"--------> CONSTANT ARRAY !"
84  CALL fill_bbuff(xtab,32,jpcstencod)
85  CALL fill_bbuff(xtab,32,knbtot)
86  CALL fill_bbuff(xtab,32,xmin)
87  CALL get_fillidx(knbuse,bitoffset)
88  knbuse=knbuse+1
89  RETURN
90 END IF
91 
92 
93 inblev = knbtot/(ilevnbelt)
94 IF (knbtot /= (inblev*ilevnbelt)) THEN
95  print *,'Pb in COMPRESS_FIELD : KNBTOT must be a multiple of KX*KY'
96  stop
97 END IF
98 
99 
100 
101 ALLOCATE(itab(ilevnbelt))
102  CALL ini_sopdata(sopres)
103 
104  CALL fill_bbuff(xtab,32,jpextencod)
105  CALL fill_bbuff(xtab,32,knbtot)
106  CALL fill_bbuff(xtab,32,kx)
107  CALL fill_bbuff(xtab,32,ky)
108 
109 DO ji=1,inblev
110  ind1=(ji-1)*ilevnbelt+1
111  ind2=ji*ilevnbelt
112  IF (lpdebug) print *,"---- Compressing Level ",ji," ----"
113  CALL comp_fopext(xworktab(ind1:ind2),itab,iextcod)
114  IF (iextcod /= jpconst) THEN
115  CALL invertcol(itab,kx,ky)
116  CALL recsearch(itab,sopres)
117  gelt = maxval(sopres%IEND(1:sopres%NBGRP)-sopres%IBEG(1:sopres%NBGRP)+1)
118  ibe = fminbits_in_word(gelt)
119  CALL get_fillidx(grpidx,grpoff) ! save the idx/offset for future NBGRP modification
120  CALL fill_bbuff(xtab,32,sopres%NBGRP)
121  CALL fill_bbuff(xtab,5,ibe)
122 
123  nbgroupmod = sopres%NBGRP
124  DO ii=1,sopres%NBGRP
125  gelt = sopres%IEND(ii)-sopres%IBEG(ii)+1
126  nbitcod = fminbits_in_word(sopres%VALMAX(ii)-sopres%VALMIN(ii))
127  ! PRINT *, 'Groupe',II,'(',GELT,')',':',SOPRES%IBEG(II),SOPRES%IEND(II),&
128  ! &'MIN,MAX=',SOPRES%VALMIN(II),SOPRES%VALMAX(II),&
129  ! &'(',SOPRES%VALMAX(II)-SOPRES%VALMIN(II),'/',&
130  ! &nbitcod,')'
131  IF (nbitcod >= 16) THEN
132  print *,'-----> ERREUR FATALE : Groupe',ii,'codage sur ',nbitcod,'bits'
133  END IF
134  IF (gelt > 1) THEN
135  ! Plus d'un element dans le groupe
136  IF ((17*gelt) < (17+4+ibe+nbitcod*gelt)) THEN
137  ! on prefere GELT groupes de 1 elt
138  DO jj=sopres%IBEG(ii),sopres%IEND(ii)
139  ! 1 seul elt par groupe
140  CALL fill_bbuff(xtab,1,1)
141  CALL fill_bbuff(xtab,16,itab(jj))
142  END DO
143  nbgroupmod = nbgroupmod+gelt-1
144  ELSE
145  CALL fill_bbuff(xtab,1,0)
146  CALL fill_bbuff(xtab,16,sopres%VALMIN(ii))
147  CALL fill_bbuff(xtab,4,nbitcod)
148  CALL fill_bbuff(xtab,ibe,gelt)
149  IF (nbitcod > 0) THEN
150  DO jj=sopres%IBEG(ii),sopres%IEND(ii)
151  ! stockage des GELT écarts/VALMIN
152  CALL fill_bbuff(xtab,nbitcod,itab(jj)-sopres%VALMIN(ii))
153  END DO
154  END IF
155  END IF
156  ELSE
157  ! 1 seul elt dans groupe
158  CALL fill_bbuff(xtab,1,1)
159  CALL fill_bbuff(xtab,16,sopres%VALMIN(ii))
160  END IF
161  END DO
162  IF (nbgroupmod > sopres%NBGRP) THEN
163  ! we must change the number of elements
164  CALL get_fillidx(idxsave,offsave) ! save the current idx/offset
165  CALL set_fillidx(grpidx,grpoff)
166  CALL fill_bbuff(xtab,32,nbgroupmod)
167  CALL set_fillidx(idxsave,offsave) ! restore the current idx/offset
168  END IF
169  END IF
170 END DO
171 
172  CALL get_fillidx(idxsave,offsave)
173 knbuse=idxsave+1
174 
175 DEALLOCATE(itab)
176 
177 CONTAINS
178 
179 SUBROUTINE comp_fopext(PTAB,KTAB,KEXTCOD)
180 REAL, DIMENSION(:), INTENT(IN) :: PTAB
181 INTEGER, DIMENSION(:), INTENT(OUT):: KTAB
182 INTEGER, INTENT(OUT):: KEXTCOD
183 
184 LOGICAL,DIMENSION(SIZE(PTAB)) :: GMASK
185 REAL :: XMIN1,XMAX1,XRANGE1
186 REAL :: XMIN2,XMAX2,XRANGE2
187 REAL :: XREF,XMAX,XCOEFF
188 INTEGER :: INTRANGE
189 INTEGER :: INDCOR ! correction d'index pour la supression du min
190 LOGICAL :: GMINEXCL,GMAXEXCL,GLOG
191 INTEGER :: IEXTCOD2
192 
193 xmin1=minval(ptab(:))
194 xmax1=maxval(ptab(:))
195 xrange1=xmax1-xmin1
196 IF (lpdebug) print *,"XMIN1,XMAX1,XRANGE1 = ",xmin1,xmax1,xrange1
197 
198 IF (xrange1 > 0.) THEN
199  xmin2=minval(ptab,mask=ptab>xmin1)
200  xmax2=maxval(ptab,mask=ptab<xmax1)
201  xrange2 = xmax2-xmin2
202  IF (lpdebug) print *,"XMIN2,XMAX2,XRANGE2 = ",xmin2,xmax2,xrange2
203  IF (xrange2 > 0.) THEN
204  glog = .false.
205  gminexcl = .false.
206  gmaxexcl = .false.
207  gmask(:) = .true.
208  indcor = 0
209  kextcod = jpnorm
210  intrange=65535
211  xref = xmin1
212  xmax = xmax1
213 
214  ! Check for range between 0 and 1 to convert to LOG values
215  IF (xmin1 >= 0. .AND. xmax1 < 1.) THEN
216  IF ((xmax2/xmin2)>10.) THEN
217  glog = .true.
218  kextcod = jpother
219  iextcod2 = jplog
220  intrange=intrange-1
221  indcor = 1 ! On reserve la valeur 0 dans tous les cas
222  IF (xmin1 == 0.0) THEN
223  xref = log(xmin2)
224  WHERE (ptab < xmin2)
225  ktab = 0
226  gmask = .false.
227  END WHERE
228  ELSE
229  xref = log(xmin1)
230  END IF
231  xmax1 = log(xmax1)
232  xmax = xmax1
233  xmax2 = log(xmax2)
234  xrange2 = xmax2 - xref
235  IF (lpdebug) print *,"EXTENCOD, LOG conversion enabled : XMIN1, XREF, XMAX1, XMAX2 =",&
236  &xmin1,xref,xmax1,xmax2
237  END IF
238  ELSE
239  ! Check for MIN value exclusion
240  IF ((xmin2-xmin1) > xrange2) THEN
241  ! Min value excluded
242  gminexcl = .true.
243  xref=xmin2
244  intrange=intrange-1
245  indcor = 1
246  WHERE (ptab < xmin2)
247  ktab = 0
248  gmask = .false.
249  END WHERE
250  IF (lpdebug) print *,"EXTENCOD, Min value isolated :",xmin1
251  kextcod = jpminexcl
252  END IF
253  ! Check for MAX value exclusion
254  IF ((xmax1-xmax2) > xrange2) THEN
255  ! Max value excluded
256  gmaxexcl = .true.
257  xmax=xmax2
258  intrange=intrange-1
259  WHERE (ptab > xmax2)
260  ktab = 65535
261  gmask = .false.
262  END WHERE
263 
264  IF (gminexcl) THEN
265  kextcod = jpminmaxexcl ! Min et Max exclus
266  IF (lpdebug) print *,"EXTENCOD, and Max value isolated :",xmax1
267  ELSE
268  kextcod = jpmaxexcl ! Max exclus
269  IF (lpdebug) print *,"EXTENCOD, Max value isolated :",xmax1
270  END IF
271  END IF
272  END IF
273  !
274  xcoeff=(xmax-xref)/intrange
275  IF (xcoeff < ppfloatmin) THEN
276  xcoeff = ppfloatmin
277  print *, "very low range DATA : XCOEFF set to",xcoeff
278  END IF
279  IF (lpdebug) print *,"XCOEFF = ",xcoeff
280  IF (glog) THEN
281  WHERE(gmask)
282  ktab = indcor + nint((log(ptab)-xref)/xcoeff)
283  END WHERE
284  ELSE
285  WHERE(gmask)
286  ktab = indcor + nint((ptab(:)-xref)/xcoeff)
287  END WHERE
288  END IF
289  IF (lpdebug) print *,"KEXTCOD = ",kextcod
290  CALL fill_bbuff(xtab,3,kextcod)
291  IF (glog) CALL fill_bbuff(xtab,3,iextcod2)
292  IF (gminexcl) CALL fill_bbuff(xtab,32,xmin1)
293  IF (gmaxexcl) CALL fill_bbuff(xtab,32,xmax1)
294  CALL fill_bbuff(xtab,32,xref)
295  CALL fill_bbuff(xtab,32,xcoeff)
296  ELSE
297  IF (xrange2 < 0.) THEN
298  ! only 2 values in PTAB array
299  !
300  ! KTAB(i)= 0 if PTAB(i)==XMIN1
301  ! 1 if PTAB(i)==XMAX1
302  !
303  IF (lpdebug) print *,"EXTENCOD, 2 values in array :",xmin1,xmax1
304  kextcod = jp2val
305  CALL fill_bbuff(xtab,3,kextcod)
306  CALL fill_bbuff(xtab,32,xmin1)
307  CALL fill_bbuff(xtab,32,xmax1)
308  WHERE (ptab < xmax1)
309  ktab = 0
310  ELSEWHERE
311  ktab = 1
312  END WHERE
313  ELSE
314  ! XRANGE2 == 0. <==> XMIN2=XMAX2
315  ! 3 values in PTAB array :
316  !
317  ! 0 if PTAB(i)==XMIN1 ! KTAB(i)= 1 if PTAB(i)==XMIN2(=XMAX2)
318  ! 2 if PTAB(i)==XMAX1
319  !
320  IF (lpdebug) print *,"EXTENCOD, 3 values in array :",xmin1,xmin2,xmax1
321  kextcod = jp3val
322  CALL fill_bbuff(xtab,3,kextcod)
323  CALL fill_bbuff(xtab,32,xmin1)
324  CALL fill_bbuff(xtab,32,xmin2)
325  CALL fill_bbuff(xtab,32,xmax1)
326  WHERE (ptab < xmin2)
327  ktab = 0
328  ELSEWHERE
329  ktab = 1
330  END WHERE
331  WHERE (ptab > xmin2) ktab = 2
332  END IF
333 
334  END IF
335 ELSE
336  ! Constant array found : save its 32 bits real value.
337  kextcod=jpconst
338  CALL fill_bbuff(xtab,3,kextcod)
339  CALL fill_bbuff(xtab,32,xmin1)
340  IF (lpdebug) print *,"EXTENCOD, constant array : ",xmin1
341 END IF
342 END SUBROUTINE comp_fopext
343 
344 END SUBROUTINE compress_field
integer, parameter jpcstencod
integer, parameter jpother
integer, parameter jpnorm
subroutine ini_sopdata(SOPDATA)
integer, parameter jp2val
subroutine invertcol(ITAB, KX, KY)
integer, external fminbits_in_word
integer, parameter jpminmaxexcl
subroutine comp_fopext(PTAB, KTAB, KEXTCOD)
integer, parameter jpextencod
logical, parameter lpdebug
integer, parameter jpconst
integer, parameter jplog
static int mask
Definition: ifssig.c:38
subroutine recsearch(KTAB, SOPDATA)
integer, parameter jp3val
integer, parameter jpminexcl
subroutine compress_field(XTAB, KX, KY, KNBTOT, KNBUSE)
integer, parameter jpmaxexcl