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