SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
read_direct_gauss.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
5 ! #########
6  SUBROUTINE read_direct_gauss (USS, &
7  hprogram,hscheme,hsubroutine,hfilename,hfield)
8 ! #########################################################
9 !
10 !!**** *READ_DIRECT_GAUSS1* reads a latlon file and call treatment subroutine
11 !!
12 !! PURPOSE
13 !! -------
14 !!
15 !! METHOD
16 !! ------
17 !!
18 !! EXTERNAL
19 !! --------
20 !!
21 !! IMPLICIT ARGUMENTS
22 !! ------------------
23 !!
24 !! REFERENCE
25 !! ---------
26 !!
27 !! AUTHOR
28 !! ------
29 !!
30 !! V. Masson Meteo-France
31 !!
32 !! MODIFICATION
33 !! ------------
34 !!
35 !! Original 11/09/95
36 !!
37 !! V. Masson, March 2010 Optimization of some lat/lon boundaries computations
38 !----------------------------------------------------------------------------
39 !
40 !* 0. DECLARATION
41 ! -----------
42 !
43 !
44 !
46 !
47 USE modd_pgd_grid, ONLY : llatlonmask, xmeshlength
48 !
49 USE modd_arch, ONLY : little_endian_arch
50 !
51 USE modi_get_luout
52 USE modi_open_namelist
53 USE modi_close_namelist
54 USE modi_open_file
55 USE modi_close_file
56 USE modi_readhead
57 USE modi_ini_ssowork
58 USE modi_pt_by_pt_treatment
60 !
61 !
62 USE yomhook ,ONLY : lhook, dr_hook
63 USE parkind1 ,ONLY : jprb
64 !
65 USE modi_abor1_sfx
66 !
67 USE modi_refresh_pgdwork
68 !
69 IMPLICIT NONE
70 !
71 !* 0.1 Declaration of arguments
72 ! ------------------------
73 !
74 !
75 TYPE(surf_atm_sso_t), INTENT(INOUT) :: uss
76 !
77  CHARACTER(LEN=6), INTENT(IN) :: hprogram ! Type of program
78  CHARACTER(LEN=6), INTENT(IN) :: hscheme ! Scheme treated
79  CHARACTER(LEN=6), INTENT(IN) :: hsubroutine ! Name of the subroutine to call
80  CHARACTER(LEN=28), INTENT(IN) :: hfilename ! Name of the field file.
81  CHARACTER(LEN=20), INTENT(IN) :: hfield ! Name of the field.
82 !
83 !* 0.2 Declaration of local variables
84 ! ------------------------------
85 !
86  CHARACTER(LEN=28) :: yfilename ! Name of the field file without header
87  CHARACTER(LEN=28) :: yfilehdr ! Name of the field file header
88 !
89  CHARACTER(LEN=7) :: ytype ! type of numerical field stored in the
90 ! ! direct access file ('INTEGER','REAL ')
91  CHARACTER(LEN=100):: ystring ! string
92  CHARACTER(LEN=88 ):: ystring1 ! part of string STRING
93 !
94  CHARACTER, DIMENSION(:), ALLOCATABLE :: yvalue8 ! value of a data point
95  CHARACTER(LEN=2), DIMENSION(:), ALLOCATABLE :: yvalue16 ! value of a data point
96  CHARACTER(LEN=4), DIMENSION(:), ALLOCATABLE :: yvalue32r ! value of a data point
97  CHARACTER(LEN=8), DIMENSION(:), ALLOCATABLE :: yvalue64 ! value of a data point
98 !
99 !
100 REAL :: zglblatmin ! minimum latitude of data box in the file
101 REAL :: zglblonmin ! minimum longitude of data box in the file
102 REAL :: zglblatmax ! maximum latitude of data box in the file
103 REAL :: zglblonmax ! maximum longitude of data box in the file
104 REAL :: znodata ! value below which data are not considered
105 REAL :: zdlat ! latitude mesh in the data file
106 REAL :: zdlon ! longitude mesh in the data file
107 REAL :: zlonmin ! minimum longitude of mask mesh
108 REAL :: zlonmax ! maximum longitude of mask mesh
109 REAL :: zlatmin ! minimum latitude of mask mesh
110 REAL :: zlatmax ! maximum latitude of mask mesh
111 REAL :: zshift ! shift on longitudes
112 REAL :: zfact ! Factor integer to real
113 !
114 REAL, DIMENSION(:), POINTER :: zlat ! latitude of data points
115 REAL, DIMENSION(:), POINTER :: zlon ! longitude of data points
116 REAL(KIND=4), DIMENSION(:), ALLOCATABLE :: zvalue32 ! value of a data point
117 REAL, DIMENSION(:), ALLOCATABLE :: zvalue ! value of a record of data points
118 REAL, DIMENSION(:), ALLOCATABLE :: zvalue_work ! value of a valid data points
119 REAL, DIMENSION(:), ALLOCATABLE :: zlat_work ! latitude of a valid data points
120 REAL, DIMENSION(:), ALLOCATABLE :: zlon_work ! longitude of a valid data points
121 !
122 INTEGER :: iindex ! index of a character in string STRING1
123 INTEGER :: ibits ! number of bits of a record in the
124  ! direct access file (16,32,64)
125 INTEGER :: ireclength ! record length
126 INTEGER :: irec ! record number
127 INTEGER :: iglb, iglbhdr ! logical units
128 INTEGER :: iluout ! output listing logical unit
129 INTEGER :: ierr ! return codes
130 !
131 INTEGER :: inbline ! number of latitude rows (number of lines
132 INTEGER :: inbcol ! number of longitude rows (number of columns)
133 INTEGER :: iline1,iline2 ! limits of index of lines
134 INTEGER :: icol ! number of columns in mask domain
135 INTEGER :: icolindex ! column index in record
136 INTEGER :: inblines, isize
137 INTEGER :: iwork ! index of these data
138 INTEGER :: jloop, jlon, jlat, jline, jcol ! loop index
139 !
140 INTEGER, DIMENSION(2) :: icol1, icol2 ! limits of index of columns
141 !
142 INTEGER (KIND=4), DIMENSION(:), ALLOCATABLE :: ivalue32 ! value of a data point
143 INTEGER (KIND=8), DIMENSION(:), ALLOCATABLE :: ivalue64 ! value of a data point
144 !
145 LOGICAL :: gswap ! T: swap has been done
146 !
147 REAL(KIND=JPRB) :: zhook_handle
148 !----------------------------------------------------------------------------
149 !
150 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_1',0,zhook_handle)
151  CALL get_luout(hprogram,iluout)
152 !
153 !* 1. Openning of global field
154 ! ------------------------
155 !
156 !* 1.1 Logical unit attributions
157 ! -------------------------
158 !
159 yfilename=adjustl(adjustr(hfilename)//'.dir')
160 yfilehdr =adjustl(adjustr(hfilename)//'.hdr')
161 !
162 !* 1.2 Openning of header
163 ! ------------------
164 !
165  CALL open_namelist(hprogram,iglbhdr,yfilehdr)
166 !
167 !* 1.3 Reading in header of direct access characteristics
168 ! --------------------------------------------------
169 !
170 DO jloop=1,9
171  READ(iglbhdr,'(A100)') ystring
172  IF (ystring(1:10)=='recordtype') EXIT
173 END DO
174 !
175 rewind(iglbhdr)
176 !
177 ystring1=ystring(12:100)
178 !
179 !* string analysis
180 !
181 iindex=index(ystring1,'n') ! n for integer
182 IF (iindex/=0) THEN
183  ytype='INTEGER'
184 ELSE
185  ytype='REAL '
186 END IF
187 iindex=index(ystring1,'8')
188 IF (iindex/=0) ibits=8
189 iindex=index(ystring1,'1')
190 IF (iindex/=0) ibits=16
191 iindex=index(ystring1,'3')
192 IF (iindex/=0) ibits=32
193 iindex=index(ystring1,'4')
194 IF (iindex/=0) ibits=64
195 !
196 IF(ytype=='INTEGER')THEN
197  IF(hfield=='CTI'.OR.hfield=='sand fraction'.OR. &
198  hfield=='clay fraction'.OR.hfield=='organic carbon')THEN
199  zfact=100.0
200  ELSEIF (hfield=='water depth') THEN
201  zfact=10.0
202  ELSE
203  zfact=1.0
204  ENDIF
205 ELSE
206  zfact=1.0
207 ENDIF
208 !
209 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_1',1,zhook_handle)
210 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_2',0,zhook_handle)
211 !----------------------------------------------------------------------------
212 !
213 !* 2. Reading of the global field
214 ! ---------------------------
215 !
216 !* 2.1 Head of data file
217 ! -----------------
218 !
219  CALL readhead(iglbhdr,zglblatmin,zglblatmax,zglblonmin,zglblonmax, &
220  inbline,inbcol,znodata,zdlat,zdlon,zlat,zlon,ierr)
221 IF (ierr/=0) CALL abor1_sfx('READ_DIRECT_GAUSS: PB IN FILE HEADER')
222 !
223 !* 2.2 Closing of header
224 ! -----------------
225 !
226  CALL close_namelist(hprogram,iglbhdr)
227 !
228 !* 2.3 Dimension of work arrays
229 ! ------------------------
230 !
231 isize = inbline*(inbcol/((zglblatmax-zglblatmin)*2.))
232 ALLOCATE(zlat_work(isize))
233 ALLOCATE(zlon_work(isize))
234 ALLOCATE(zvalue_work(isize))
235 !
236 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_2',1,zhook_handle)
237 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_3',0,zhook_handle)
238 !----------------------------------------------------------------------------
239 !
240 !* 3. Adapt subgrid mesh to input file resolution
241 ! -------------------------------------------
242 !
243 IF (hsubroutine=='A_OROG') CALL ini_ssowork(xmeshlength,zdlat,zdlon)
244 !
245 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_3',1,zhook_handle)
246 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_4',0,zhook_handle)
247 !----------------------------------------------------------------------------
248 !
249 !* 7. Openning of direct access file
250 ! ------------------------------
251 !
252 !* 7.1 Record length
253 ! -------------
254 !
255 ireclength = ibits/8 * inbcol
256 ALLOCATE (zvalue(inbcol))
257 IF (ytype=='INTEGER' .AND. ibits== 8) THEN
258  ALLOCATE (yvalue8(inbcol))
259 ELSEIF (ytype=='INTEGER' .AND. ibits==16) THEN
260  ALLOCATE (yvalue16(inbcol))
261 ELSEIF (ytype=='INTEGER' .AND. ibits==32) THEN
262  ALLOCATE (ivalue32(inbcol))
263  ELSEIF (ytype=='INTEGER' .AND. ibits==64) THEN
264  ALLOCATE (ivalue64(inbcol))
265 ELSEIF (ytype=='REAL ' .AND. ibits==32) THEN
266  ALLOCATE (yvalue32r(inbcol))
267 ELSEIF (ytype=='REAL ' .AND. ibits==64) THEN
268  ALLOCATE (yvalue64(inbcol))
269 ENDIF
270 !
271 !* 7.2 Openning of direct access file
272 ! ------------------------------
273 !
274  CALL open_file(hprogram,iglb,yfilename,'UNFORMATTED', &
275  haction='READ',haccess='DIRECT',krecl=ireclength )
276 !
277 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_4',1,zhook_handle)
278 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_5',0,zhook_handle)
279 !----------------------------------------------------------------------------
280 !
281 !* 4. loop on mask meshes (lat)
282 ! -------------------
283 !
284 gswap = .false.
285 !
286 jlat = 0
287 !
288 DO
289  !
290  jlat = jlat + 1
291  IF (jlat==361) EXIT
292  !
293  IF ( .NOT. any(llatlonmask(:,jlat)) ) cycle
294  !
295  zlatmin = (jlat-180)/2. - 0.5
296  zlatmax = (jlat-180)/2.
297  !
298  !----------------------------------------------------------------------------
299  !
300  !* 5. index limits on latitude
301  ! ------------------------
302  !
303  iline1=max(min(int((zglblatmax-zdlat/2.-zlatmax)/zdlat+1.),inbline),0)+1
304  iline2=max(min(int((zglblatmax-zdlat/2.-zlatmin)/zdlat+1.),inbline),0)
305  IF ( .NOT. any(zlat(:)<zlatmax .AND. zlat(:)>=zlatmin) ) cycle
306  !
307  !----------------------------------------------------------------------------
308  !
309  !* 8. Loop on lines
310  ! -------------
311  !
312  iwork=0
313  DO jline = iline1,iline2
314  !
315  inblines = iline2 - iline1 + 1
316  !----------------------------------------------------------------------------
317  !
318  !* 10. Reading in the direct access file
319  ! ---------------------------------
320  !
321  !* 10.1 Record number
322  ! -------------
323  !
324  irec=jline
325  !
326  !* 10.2 Reading the correct data type and conversion into real
327  ! ------------------------------------------------------
328  !
329  IF (ytype=='INTEGER' .AND. ibits== 8) THEN
330  READ(iglb,rec=irec) yvalue8(:)
331  zvalue(:)=yvalue8(:)
332  ! negative values are shifted to positive values according to binary coding
333  WHERE (zvalue(:)<0.) zvalue(:) = nint(256.+zvalue(:))
334  !
335  ELSE IF (ytype=='INTEGER' .AND. ibits==16) THEN
336  READ(iglb,rec=irec) yvalue16(:)
337  zvalue(:)=yvalue16(:)
338  !
339  IF ( any(abs(zvalue)>15000) ) THEN
340  IF (gswap) CALL abor1_sfx('READ_DIRECT_GAUSS: SWAP ALREADY DONE, CANNOT BE REDONE')
341  little_endian_arch = .NOT. little_endian_arch
342  gswap = .true.
343  WRITE(iluout,*) '*******************************************************************'
344  WRITE(iluout,*) 'Architecture of the machine needs to swap LITTLE_ENDIAN_ARCH to ', &
345  little_endian_arch
346  WRITE(iluout,*) '*******************************************************************'
347  jlat = 0
348  CALL refresh_pgdwork
349  EXIT ! rereads the file
350  END IF
351  !
352  ELSE IF (ytype=='INTEGER' .AND. ibits==32) THEN
353  READ(iglb,rec=irec) ivalue32(:)
354  zvalue(:)=ivalue32(:)
355  !
356  ELSE IF (ytype=='INTEGER' .AND. ibits==64) THEN
357  READ(iglb,rec=irec) ivalue64(:)
358  zvalue(:)=ivalue64(:)
359  !
360  ELSE IF (ytype=='REAL ' .AND. ibits==32) THEN
361  READ(iglb,rec=irec) yvalue32r(:)
362  zvalue(:)=yvalue32r(:)
363  !
364  IF ( any(abs(zvalue)>0. .AND. abs(zvalue)<1.e-50) &
365  .OR. any(abs(zvalue)>1.e20) ) THEN
366  IF (gswap) CALL abor1_sfx('READ_DIRECT_GAUSS: SWAP ALREADY DONE, CANNOT BE REDONE')
367  little_endian_arch = .NOT. little_endian_arch
368  gswap = .true.
369  WRITE(iluout,*) '*******************************************************************'
370  WRITE(iluout,*) 'Architecture of the machine needs to swap LITTLE_ENDIAN_ARCH to ', &
371  little_endian_arch
372  WRITE(iluout,*) '*******************************************************************'
373  jlat = 0
374  CALL refresh_pgdwork
375  EXIT
376  END IF
377  !
378  ELSE IF (ytype=='REAL ' .AND. ibits==64) THEN
379  READ(iglb,rec=irec) yvalue64(:)
380  zvalue(:)=yvalue64(:)
381  !
382  IF ( any(abs(zvalue)>0. .AND. abs(zvalue)<1.e-50) &
383  .OR. any(abs(zvalue)>1.e20) ) THEN
384  IF (gswap) CALL abor1_sfx('READ_DIRECT_GAUSS: SWAP ALREADY DONE, CANNOT BE REDONE')
385  little_endian_arch = .NOT. little_endian_arch
386  gswap = .true.
387  WRITE(iluout,*) '*******************************************************************'
388  WRITE(iluout,*) 'Architecture of the machine needs to swap LITTLE_ENDIAN_ARCH to ', &
389  little_endian_arch
390  WRITE(iluout,*) '*******************************************************************'
391  jlat = 0
392  CALL refresh_pgdwork
393  EXIT
394  END IF
395  !
396  ELSE
397  CALL abor1_sfx('READ_DIRECT_GAUSS1: DATA TYPE NOT SUPPORTED')
398  END IF
399  !
400  IF(hfield=='CTI')THEN
401  WHERE(zvalue(:)<0.0) zvalue(:)=znodata
402  ENDIF
403  !
404  WHERE(zvalue(:)/=znodata)zvalue(:)=zvalue(:)/zfact
405  !
406  !----------------------------------------------------------------------------
407  !
408  !* 4. loop on mask meshes (lon)
409  ! -------------------
410  !
411  DO jlon=1,720
412  !
413  IF (.NOT. llatlonmask(jlon,jlat)) cycle
414  !
415  zlonmin = jlon /2. - 0.5
416  zlonmax = jlon /2.
417  !
418  !----------------------------------------------------------------------------
419  !
420  !* 5. limits on longitude
421  ! -------------------
422  !
423  !* 5.1 left domain border is set just higher than the global field min. longitude
424  ! -----------------------------------------------------------------
425  !
426  zshift = 360. * nint((zlonmin-zglblonmin-180.+1.e-10)/360.)
427  !
428  zglblonmin = zglblonmin + zshift
429  zglblonmax = zglblonmax + zshift
430  !
431  !* 5.2 index limits on longitude
432  ! -------------------------
433  !
434  icol1(1)=max(min(int((zlonmin-zglblonmin-zdlon/2.)/zdlon+1.),inbcol),0)+1
435  icol2(1)=max(min(int((zlonmax-zglblonmin-zdlon/2.)/zdlon+1.),inbcol),0)
436  !
437  !* Does right domain border goes outside the global field longitude range?
438  !* Does it then goes into the global field domain by the other side?
439  !* Then a second part of the global field domain must be considered
440  !
441  icol1(2)=1
442  icol2(2)=max(min(int((zlonmax-zglblonmin-zdlon/2.-360.)/zdlon+1.),inbcol),0)
443  !
444  !----------------------------------------------------------------------------
445  !
446  !* 6. Loop on longitude limits
447  ! ------------------------
448  !
449  DO jloop=1,2
450  !
451  icol = icol2(jloop) - icol1(jloop) + 1
452  !
453  IF (icol<1) cycle
454  !
455  !----------------------------------------------------------------------------
456  !
457  !* 11. Loop on columns
458  ! ---------------
459  !
460  DO jcol=1,icol
461  !
462  !* 11.1 Recovers point value
463  ! --------------------
464  !
465  icolindex = jcol+icol1(jloop)-1
466  !
467  !* 11.2 Test with respect to the 'no data' value
468  ! ----------------------------------------
469  !
470  !* 11.3 copy of the correct values in a work array
471  ! ------------------------------------------
472  !
473  iwork = iwork + 1
474  zlat_work(iwork) = zlat(jline)
475  zlon_work(iwork) = zlon(icolindex)
476  zvalue_work(iwork) = zvalue(icolindex)
477  !
478  END DO ! JCOL
479  !-------------------------------------------------------------------------------
480  END DO !JLOOP
481  !-------------------------------------------------------------------------------
482  END DO !JLON
483  !-------------------------------------------------------------------------------
484  END DO ! JLINE
485  !-------------------------------------------------------------------------------
486  !
487  !* 12. Call to the adequate subroutine (point by point treatment)
488  ! ----------------------------------------------------------
489  !
490  IF (iwork>0) &
491  CALL pt_by_pt_treatment(uss, &
492  iluout, zlat_work(1:iwork),zlon_work(1:iwork), &
493  zvalue_work(1:iwork), &
494  hsubroutine, inblines, znodata )
495 !
496 !-------------------------------------------------------------------------------
497 END DO !JLAT
498 !
499 !-------------------------------------------------------------------------------
500 !
501 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_5',1,zhook_handle)
502 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_6',0,zhook_handle)
503 
504 DEALLOCATE(zlat)
505 DEALLOCATE(zlon)
506 !
507 DEALLOCATE(zlat_work )
508 DEALLOCATE(zlon_work )
509 DEALLOCATE(zvalue_work)
510 !
511 DEALLOCATE (zvalue)
512 IF (ALLOCATED(yvalue8)) DEALLOCATE (yvalue8 )
513 IF (ALLOCATED(yvalue16)) DEALLOCATE (yvalue16)
514 IF (ALLOCATED(yvalue32r)) DEALLOCATE (yvalue32r)
515 IF (ALLOCATED(yvalue64)) DEALLOCATE (yvalue64)
516 IF (ALLOCATED(ivalue32)) DEALLOCATE (ivalue32)
517 IF (ALLOCATED(ivalue64)) DEALLOCATE (ivalue64)
518 IF (ALLOCATED(zvalue32)) DEALLOCATE (zvalue32)
519 !
520  CALL close_file(hprogram,iglb)
521 !
522 IF (lhook) CALL dr_hook('READ_DIRECT_GAUSS_6',1,zhook_handle)
523 !
524 !-------------------------------------------------------------------------------
525 !
526 END SUBROUTINE read_direct_gauss
subroutine pt_by_pt_treatment(USS, KLUOUT, PLAT, PLON, PVALUE, HSUBROUTINE, KNBLINES, PNODATA)
subroutine abor1_sfx(YTEXT)
Definition: abor1_sfx.F90:6
subroutine refresh_pgdwork
subroutine readhead(KGLB, PGLBLATMIN, PGLBLATMAX, PGLBLONMIN, PGLBLONMAX, KNBLAT, KNBLON, PCUTVAL, PDLAT, PDLON, PLAT, PLON, KERR)
Definition: readhead.F90:6
subroutine ini_ssowork(PMESHLENGTH, PDLAT, PDLON)
Definition: ini_ssowork.F90:6
subroutine close_namelist(HPROGRAM, KLUNAM)
subroutine close_file(HPROGRAM, KUNIT)
Definition: close_file.F90:6
subroutine get_luout(HPROGRAM, KLUOUT)
Definition: get_luout.F90:6
subroutine open_namelist(HPROGRAM, KLUNAM, HFILE)
subroutine read_direct_gauss(USS, HPROGRAM, HSCHEME, HSUBROUTINE, HFILENAME, HFIELD)
subroutine open_file(HPROGRAM, KUNIT, HFILE, HFORM, HACTION, HACCESS, KRECL)
Definition: open_file.F90:6