SURFEX v8.1
General documentation of Surfex
ol_read_atm_conf_netcdf.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 ol_read_atm_conf_netcdf (DTCO, U, HGRID, HSURF_FILETYPE, ODELAYEDSTART_NC, KDATESTOP, &
7  PDURATION, PTSTEP_FORC, KNI, KYEAR, KMONTH, KDAY, PTIME, &
8  PLAT, PLON, PZS, PZREF, PUREF,KTIMESTARTINDEX )
9 !
10 !==================================================================
11 !!**** *OL_READ_ATM_CONF* - Initialization routine
12 !!
13 !! PURPOSE
14 !! -------
15 !!
16 !!** METHOD
17 !! ------
18 !!
19 !! EXTERNAL
20 !! --------
21 !!
22 !!
23 !! IMPLICIT ARGUMENTS
24 !! ------------------
25 !!
26 !! REFERENCE
27 !! ---------
28 !!
29 !!
30 !! AUTHOR
31 !! ------
32 !! F. Habets *Meteo France*
33 !!
34 !! MODIFICATIONS
35 !! -------------
36 !! Original 01/2004
37 !! Modified by P. Le Moigne (04/2005): cleaning and checking
38 !! Modified by P. Le Moigne (04/2006): init_io_surf for nature
39 !! with GTMSK to read dimensions.
40 !! Modified by Matthieu Lafaysse 2012-11-12
41 !==================================================================
42 !
43 !
45 USE modd_surf_atm_n, ONLY : surf_atm_t
46 !
48 !
50 !
51 USE modi_set_surfex_filein
52 USE modi_get_luout
53 USE modi_init_io_surf_n
55 USE modi_end_io_surf_n
56 USE modi_get_size_full_n
57 USE modi_abor1_sfx
58 !
60 !
61 USE yomhook ,ONLY : lhook, dr_hook
62 USE parkind1 ,ONLY : jprb
63 !
64 USE netcdf
65 !
66 IMPLICIT NONE
67 !
68 #ifdef SFX_MPI
69 include "mpif.h"
70 #endif
71 !
72 TYPE(data_cover_t), INTENT(INOUT) :: DTCO
73 TYPE(surf_atm_t), INTENT(INOUT) :: U
74 !
75  CHARACTER(LEN=*), INTENT(IN) :: HGRID
76  CHARACTER(LEN=6), INTENT(IN) :: HSURF_FILETYPE
77 LOGICAL, INTENT(IN) :: ODELAYEDSTART_NC ! Allow the simulation to start from a different time step than the first record of a netcdf file
78 INTEGER,DIMENSION(4),INTENT(IN) :: KDATESTOP !Allow the simulation to end at a different time step than the last record of a netcdf file
79 INTEGER, INTENT(OUT) :: KNI
80 INTEGER, INTENT(OUT) :: KYEAR, KMONTH, KDAY
81 REAL, INTENT(OUT) :: PDURATION,PTSTEP_FORC
82 REAL, INTENT(OUT) :: PTIME
83 REAL, DIMENSION(:), POINTER :: PLAT, PLON
84 REAL, DIMENSION(:), POINTER :: PZS
85 REAL, DIMENSION(:), POINTER :: PZREF, PUREF
86 INTEGER, INTENT(OUT) :: KTIMESTARTINDEX ! index from which we start reading FORCING.nc
87 !
88  CHARACTER(LEN=100) :: YUNITS
89 REAL, DIMENSION(:), POINTER :: ZTIMEFILE
90 REAL,DIMENSION(:),ALLOCATABLE :: ZLAT1D, ZLON1D
91 REAL :: ZTIME
92 REAL :: ZFIRSTTIMEFILE
93 INTEGER :: IYEAR, IMONTH, IDAY
94 INTEGER :: IRET, INB_FORC
95 INTEGER :: INI, IDIM_FULL
96 INTEGER :: ILUOUT
97 INTEGER :: JINDEX
98 INTEGER :: INFOMPI
99 type(date_time) :: ttime
100 type(date_time), DIMENSION(1) :: tz_firstdatefile
101 type(date_time), DIMENSION(:), ALLOCATABLE :: tz_datefile
102 INTEGER :: JPOINT, INLAT1D, INLON1D
103 LOGICAL :: GLONLAT1D
104 DOUBLE PRECISION :: XTIME0
105 REAL(KIND=JPRB) :: ZHOOK_HANDLE
106 !
107 !==================================================================
108 !
109 !* 0. IO initialization
110 !
111 IF (lhook) CALL dr_hook('OL_READ_ATM_CONF_NETCDF',0,zhook_handle)
112 !
113 IF (nrank==npio) THEN
114  !
115 #ifdef SFX_MPI
116  xtime0 = mpi_wtime()
117 #endif
118  !
119  CALL get_luout(hsurf_filetype,iluout)
120  !
121  !* 1. Read parameters from netcdf forcing file
122  !
123  yunits = ""
124  CALL read_surf_dim_ol(yunits, inb_forc, ini, zfirsttimefile, iret,&
125  glonlat1d, inlon1d, inlat1d, ztimefile)
126  !
127 #ifdef SFX_MPI
128  xtime_npio_read = xtime_npio_read + (mpi_wtime() - xtime0)
129 #endif
130  !
131 ENDIF
132 !
133 IF (nproc>1) THEN
134 #ifdef SFX_MPI
135  xtime0 = mpi_wtime()
136  CALL mpi_bcast(inb_forc,kind(inb_forc)/4,mpi_integer,npio,ncomm,infompi)
137  CALL mpi_bcast(glonlat1d,1,mpi_logical,npio,ncomm,infompi)
138  CALL mpi_bcast(inlon1d,kind(inlon1d)/4,mpi_integer,npio,ncomm,infompi)
139  CALL mpi_bcast(inlat1d,kind(inlat1d)/4,mpi_integer,npio,ncomm,infompi)
140  xtime_comm_read = xtime_comm_read + (mpi_wtime() - xtime0)
141 #endif
142 ENDIF
143 !
144  CALL read_surf(&
145  'OFFLIN','FRC_TIME_STP' ,ptstep_forc ,iret)
146 !
147 pduration = ( inb_forc - 1 ) * ptstep_forc
148 !
149 !* 2. Read full grid dimension and date
150 !
151  CALL set_surfex_filein(hsurf_filetype,'PREP')
152  CALL init_io_surf_n(dtco, u, hsurf_filetype,'FULL ','SURF ','READ ')
153 !
154  CALL read_surf(hsurf_filetype,'DIM_FULL',idim_full,iret)
155  CALL read_surf(hsurf_filetype,'DTCUR',ttime,iret)
156 !
157 kyear = ttime%TDATE%YEAR
158 kmonth = ttime%TDATE%MONTH
159 kday = ttime%TDATE%DAY
160 ptime = ttime%TIME
161 !
162  CALL end_io_surf_n(hsurf_filetype)
163 !
164 !* 5. Geographical initialization
165 !
166  CALL get_size_full_n('OFFLIN ',idim_full,u%NSIZE_FULL,kni)
167 !
168 ALLOCATE(plon(kni))
169 ALLOCATE(plat(kni))
170 ALLOCATE(pzs(kni))
171 ALLOCATE(pzref(kni))
172 ALLOCATE(puref(kni))
173 !
174 IF (glonlat1d) THEN
175  ALLOCATE(zlat1d(inlat1d))
176  ALLOCATE(zlon1d(inlon1d))
177  ! we have to read PLAT and PLON due to parallel IO.
178  ! however lat / lon have just INLAT1D and INLON1D dimension lengths in the netcdf file
179  CALL read_surf('OFFLIN','LAT',plat,iret)
180  CALL read_surf('OFFLIN','LON',plon,iret)
181  zlat1d=plat(1:inlat1d)
182  zlon1d=plon(1:inlon1d)
183 ELSE
184  CALL read_surf('OFFLIN','LAT',plat,iret)
185  CALL read_surf('OFFLIN','LON',plon,iret)
186 ENDIF
187 !
188  CALL read_surf('OFFLIN','ZS',pzs,iret)
189  CALL read_surf('OFFLIN','ZREF',pzref,iret)
190  CALL read_surf('OFFLIN','UREF',puref,iret)
191 !
192 ! Modif Matthieu Lafaysse
193 ! If LON LAT REGULAR grid and 1 dimension LON LAT variables
194 ! Affect 1d lon lat to total tables
195 IF (glonlat1d) THEN
196  !
197  IF ( inlat1d*inlon1d==idim_full ) THEN
198  DO jpoint = 1,idim_full
199  plat(jpoint) = zlat1d((jpoint-1)/inlon1d+1)
200  plon(jpoint) = zlon1d(mod(jpoint-1,inlon1d)+1)
201  END DO
202  DEALLOCATE(zlat1d)
203  DEALLOCATE(zlon1d)
204  ELSE
205  WRITE(iluout,*)' NUMBER OF GRID POINTS INCONSISTENCY: ',idim_full,'/',inlat1d*inlon1d
206  CALL abor1_sfx('OL_READ_ATM_CONF_NETCDF: NUMBER OF GRID POINTS INCONSISTENCY')
207  END IF
208 END IF
209 !
210 !* 6. Check the consistency
211 !
212 IF (nrank == npio) THEN
213  !
214  IF (idim_full /= ini) THEN
215  WRITE(iluout,*)' NUMBER OF GRID POINTS INCONSISTENCY: ',idim_full,'/',ini
216  CALL abor1_sfx('OL_READ_ATM_CONF_NETCDF: NUMBER OF GRID POINTS INCONSISTENCY')
217  ENDIF
218  !
219  IF ( odelayedstart_nc .OR. kdatestop(1)/=0 ) THEN
220  !
221  ! Convert time variable in dates
222  ALLOCATE(tz_datefile(inb_forc))
223  CALL netcdf2date(ztimefile, yunits, tz_datefile)
224  !
225  END IF
226  DEALLOCATE(ztimefile)
227  !
228  IF ( odelayedstart_nc ) THEN
229  !
230  ktimestartindex = -1
231  !
232  ! Look for a date equal to the date prescribed in OPTIONS.NAM
233  DO jindex = 1,inb_forc
234  iyear = tz_datefile(jindex)%TDATE%YEAR
235  imonth = tz_datefile(jindex)%TDATE%MONTH
236  iday = tz_datefile(jindex)%TDATE%DAY
237  ztime = tz_datefile(jindex)%TIME* 3600.
238 
239  IF ( kyear==iyear .AND. kmonth==imonth .AND. kday==iday .AND. ptime==ztime ) THEN
240  ktimestartindex = jindex
241  inb_forc = inb_forc-ktimestartindex+1
242  pduration = ( inb_forc - 1 ) * ptstep_forc
243  EXIT
244  END IF
245 
246  END DO
247 
248  ! Error if the initial date is not found
249  IF ( ktimestartindex==-1 ) THEN
250  WRITE(iluout,*)'IN THE FORCING FILE, WE CAN NOT FIND THIS INITIAL DATE :',kyear,kmonth,kday,ptime
251  CALL abor1_sfx('OL_READ_ATM_CONF_NETCDF: DATE INCONSISTENCY')
252  END IF
253 
254  ELSE
255 
256  ktimestartindex = 1
257 
258  CALL netcdf2date((/zfirsttimefile/),yunits,tz_firstdatefile)
259  iyear = tz_firstdatefile(1)%TDATE%YEAR
260  imonth = tz_firstdatefile(1)%TDATE%MONTH
261  iday = tz_firstdatefile(1)%TDATE%DAY
262  ztime = tz_firstdatefile(1)%TIME* 3600.
263  !
264  IF ( (kyear /= iyear) .OR. (kmonth /= imonth) .OR. (kday /= iday) ) THEN
265  WRITE(iluout,*)' DATE INCONSISTENCY: ',kyear,kmonth,kday,'/',iyear,imonth,iday
266  CALL abor1_sfx('OL_READ_ATM_CONF_NETCDF: DATE INCONSISTENCY')
267  ENDIF
268  !
269  IF ( ptime /= ztime ) THEN
270  WRITE(iluout,*)' TIME INCONSISTENCY: ',ptime,'/',ztime
271  CALL abor1_sfx('OL_READ_ATM_CONF_NETCDF: TIME INCONSISTENCY')
272  ENDIF
273  !
274  ENDIF
275  !
276  ! Look for the prescribed final date to modify PDURATION
277  ! If we don't find it, ignore.
278  IF ( kdatestop(1)/=0 ) THEN
279  !
280  DO jindex = ktimestartindex,inb_forc+ktimestartindex-1
281  iyear = tz_datefile(jindex)%TDATE%YEAR
282  imonth = tz_datefile(jindex)%TDATE%MONTH
283  iday = tz_datefile(jindex)%TDATE%DAY
284  ztime = tz_datefile(jindex)%TIME* 3600.
285  IF ( kdatestop(1)==iyear .AND. kdatestop(2)==imonth .AND. kdatestop(3)==iday &
286  .AND. kdatestop(4)==int(ztime) ) THEN
287  inb_forc = jindex-ktimestartindex+1
288  pduration = ( inb_forc - 1 ) * ptstep_forc
289  EXIT
290  END IF
291  END DO
292  !
293  END IF
294  !
295  IF ( odelayedstart_nc .OR. kdatestop(1)/=0 ) THEN
296  DEALLOCATE(tz_datefile)
297  END IF
298  !
299 ENDIF
300 !
301 IF (nproc>1) THEN
302 #ifdef SFX_MPI
303  xtime0 = mpi_wtime()
304  CALL mpi_bcast(ktimestartindex,kind(ktimestartindex)/4,mpi_integer,npio,ncomm,infompi)
305  CALL mpi_bcast(pduration,kind(pduration)/4,mpi_real,npio,ncomm,infompi)
306  xtime_comm_read = xtime_comm_read + (mpi_wtime() - xtime0)
307 #endif
308 ENDIF
309 !
310 IF (lhook) CALL dr_hook('OL_READ_ATM_CONF_NETCDF',1,zhook_handle)
311 !==================================================================
312 CONTAINS
313 !
314 ! #############################################################
315  SUBROUTINE read_surf_dim_ol(HUNITS,KSIZE,KNI,PFIRSTTIMEFILE,KRESP,&
316  OLONLAT1D,KNLON1D,KNLAT1D,PTIMEFILE)
317 ! #############################################################
318 !
319 USE modi_ol_find_file_read
320 !
321 USE netcdf
322 !
323 IMPLICIT NONE
324 !
325 !* 0.1 Declarations of arguments
326 !
327  CHARACTER(LEN=100), INTENT(OUT) :: HUNITS
328 INTEGER, INTENT(OUT) :: KSIZE
329 INTEGER, INTENT(OUT) :: KNI
330 REAL, INTENT(OUT) :: PFIRSTTIMEFILE
331 INTEGER, INTENT(OUT) :: KRESP
332 LOGICAL, INTENT(OUT) :: OLONLAT1D
333 INTEGER, INTENT(OUT) :: KNLON1D,KNLAT1D
334 REAL,DIMENSION(:), POINTER, INTENT(OUT) :: PTIMEFILE
335 !
336 !* 0.2 Declarations of local variables
337 !
338 INTEGER :: IFILE_ID,IVAR_ID,INDIMS,JRET,JDIM,ITYPE
339 INTEGER,DIMENSION(2) :: IDIMIDS,IDIMLEN
340  CHARACTER(20),DIMENSION(2) :: YDIMNAMES
341 INTEGER,DIMENSION(8) :: IRET
342 
343 REAL*4, DIMENSION(:), ALLOCATABLE :: ZTIMEFILE4
344 REAL, DIMENSION(:), ALLOCATABLE :: ZTIMEFILE
345 INTEGER, DIMENSION(:), ALLOCATABLE :: ITIMEFILE
346 !
347 REAL(KIND=JPRB) :: ZHOOK_HANDLE
348 !-------------------------------------------------------------------------------
349 
350 IF (lhook) CALL dr_hook('OL_READ_ATM_CONF_NETCDF:READ_SURF_DIM_OL',0,zhook_handle)
351 kresp=0
352 
353 ! 0. find filename
354 ! -----------------
355  CALL ol_find_file_read('time',ifile_id)
356 
357 IF (ifile_id.NE.0) THEN
358 
359  ! 1. Find id of the variable
360  !----------------------------
361  iret(1)=nf90_inq_varid(ifile_id,'time',ivar_id)
362  iret(2)=nf90_inquire_variable(ifile_id,ivar_id,ndims=indims)
363  iret(3)=nf90_inquire_variable(ifile_id,ivar_id,dimids=idimids(1:1))
364  iret(4)=nf90_inquire_dimension(ifile_id,idimids(1),len=ksize)
365  iret(5)=nf90_get_att(ifile_id,ivar_id,'units',hunits)
366 
367  iret(6)=nf90_inquire_variable(ifile_id,ivar_id,xtype=itype)
368 
369  ALLOCATE(ptimefile(ksize))
370 
371  SELECT CASE (itype)
372  CASE (nf90_double)
373  ALLOCATE(ztimefile(ksize))
374  iret(7)=nf90_get_var(ifile_id,ivar_id,ztimefile)
375  pfirsttimefile=ztimefile(1)
376  ptimefile(:)=ztimefile(:)
377  DEALLOCATE(ztimefile)
378  CASE (nf90_float)
379  ALLOCATE(ztimefile4(ksize))
380  iret(7)=REAL(nf90_get_var(ifile_id,ivar_id,ztimefile4))
381  pfirsttimefile=ztimefile4(1)
382  ptimefile(:)=ztimefile4(:)
383  DEALLOCATE(ztimefile4)
384  CASE (nf90_int)
385  ALLOCATE(itimefile(ksize))
386  iret(7)=REAL(nf90_get_var(ifile_id,ivar_id,itimefile))
387  pfirsttimefile=itimefile(1)
388  ptimefile(:)=itimefile(:)
389  DEALLOCATE(itimefile)
390  CASE DEFAULT
391  CALL abor1_sfx('OL_READ_ATM_CONF_NETCDF: TYPE OF TIME VARIABLE NOT KNOWN')
392  END SELECT
393 
394  ! 3. Check for errors
395  !--------------------
396  DO jret=1,7
397  IF (ifile_id==0.OR.iret(jret).NE.nf90_noerr) kresp=1
398  ENDDO
399 
400 ENDIF
401 
402  CALL ol_find_file_read('LON',ifile_id)
403 !
404 olonlat1d = .false.
405 knlat1d = 0
406 knlon1d = 0
407 !
408 IF (ifile_id.NE.0) THEN
409 
410  iret(1)=nf90_inq_varid(ifile_id,'LON',ivar_id)
411  iret(2)=nf90_inquire_variable(ifile_id,ivar_id,ndims=indims)
412  iret(3)=nf90_inquire_variable(ifile_id,ivar_id,dimids=idimids(:))
413  idimlen(:)=1.
414  DO jdim=1,indims
415  iret(4)=nf90_inquire_dimension(ifile_id,idimids(jdim),name=ydimnames(jdim),len=idimlen(jdim))
416  ENDDO
417 !
418  IF ( hgrid.EQ.'LONLAT REG' .AND. indims==1 ) THEN
419  IF (trim(ydimnames(1))/="Number_of_points") THEN
420  ! Modif Matthieu Lafaysse
421  ! If LON LAT REGULAR grid and 1 dimension LON LAT variables
422  ! total dimension is nlon*nlat
423 
424  olonlat1d = .true.
425  CALL ol_find_file_read('LAT',ifile_id)
426  iret(5) = nf90_inq_varid(ifile_id,'LAT',ivar_id)
427  iret(6) = nf90_inquire_variable(ifile_id,ivar_id,ndims=indims)
428  IF ( indims==1 ) THEN
429  iret(7) = nf90_inquire_variable(ifile_id,ivar_id,dimids=idimids(2:2))
430  iret(8) = nf90_inquire_dimension(ifile_id,idimids(2),len=idimlen(2))
431  knlon1d = idimlen(1)
432  knlat1d = idimlen(2)
433  ELSE
434  kresp = 1
435  END IF
436  END IF
437  END IF
438  kni = idimlen(1) * idimlen(2)
439 
440  DO jret=1,4
441  IF (ifile_id==0.OR.iret(jret).NE.nf90_noerr) kresp=1
442  ENDDO
443 
444 ENDIF
445 !
446 IF (lhook) CALL dr_hook('OL_READ_ATM_CONF_NETCDF:READ_SURF_DIM_OL',1,zhook_handle)
447 !-------------------------------------------------------------------------------
448 END SUBROUTINE read_surf_dim_ol
449 !
450 END SUBROUTINE ol_read_atm_conf_netcdf
subroutine netcdf2date(PTIME, HUNITS, PDATETIME)
subroutine set_surfex_filein(HPROGRAM, HMASK)
subroutine read_surf_dim_ol(HUNITS, KSIZE, KNI, PFIRSTTIMEFILE, KRESP, OLONLAT1D, KNLON1D, KNLAT1D, PTIMEFILE)
quick &counting sorts only inumt inumt name
subroutine get_size_full_n(HPROGRAM, KDIM_FULL, KSIZE_FULL_IN, KSIZE
subroutine ol_find_file_read(HNAME, IFILE_ID)
subroutine abor1_sfx(YTEXT)
Definition: abor1_sfx.F90:7
integer, parameter jprb
Definition: parkind1.F90:32
subroutine end_io_surf_n(HPROGRAM)
Definition: end_io_surfn.F90:7
subroutine get_luout(HPROGRAM, KLUOUT)
Definition: get_luout.F90:7
logical lhook
Definition: yomhook.F90:15
subroutine init_io_surf_n(DTCO, U, HPROGRAM, HMASK, HSCHEME, HACTION
subroutine ol_read_atm_conf_netcdf(DTCO, U, HGRID, HSURF_FILETYPE, ODELAYEDSTART_NC, KDATESTOP, PDURATION, PTSTEP_FORC, KNI, KYEAR, KMONTH, KDAY, PTIME, PLAT, PLON, PZS, PZREF, PUREF, KTIMESTARTINDEX)