New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
iom_nf90.F90 in branches/2014/dev_r4650_UKMO11_restart_functionality/NEMOGCM/NEMO/OPA_SRC/IOM – NEMO

source: branches/2014/dev_r4650_UKMO11_restart_functionality/NEMOGCM/NEMO/OPA_SRC/IOM/iom_nf90.F90 @ 4775

Last change on this file since 4775 was 4775, checked in by edblockley, 10 years ago

First round of chnages for restart functionality branch (UKMO11).

These changes add namelist variables to allow the user to specify the directory to read input restart files and write output restart files for NEMO & LIM2/3.

  • Property svn:keywords set to Id
File size: 34.1 KB
Line 
1MODULE iom_nf90
2   !!=====================================================================
3   !!                    ***  MODULE  iom_nf90 ***
4   !! Input/Output manager :  Library to read input files with NF90 (only fliocom module)
5   !!====================================================================
6   !! History :  9.0  ! 05 12  (J. Belier) Original code
7   !!            9.0  ! 06 02  (S. Masson) Adaptation to NEMO
8   !!             "   ! 07 07  (D. Storkey) Changes to iom_nf90_gettime
9   !!--------------------------------------------------------------------
10   !!gm  caution add !DIR nec: improved performance to be checked as well as no result changes
11
12   !!--------------------------------------------------------------------
13   !!   iom_open       : open a file read only
14   !!   iom_close      : close a file or all files opened by iom
15   !!   iom_get        : read a field (interfaced to several routines)
16   !!   iom_gettime    : read the time axis kvid in the file
17   !!   iom_varid      : get the id of a variable in a file
18   !!   iom_rstput     : write a field in a restart file (interfaced to several routines)
19   !!--------------------------------------------------------------------
20   USE dom_oce         ! ocean space and time domain
21   USE lbclnk          ! lateal boundary condition / mpp exchanges
22   USE iom_def         ! iom variables definitions
23   USE netcdf          ! NetCDF library
24   USE in_out_manager  ! I/O manager
25   USE lib_mpp         ! MPP library
26
27   IMPLICIT NONE
28   PRIVATE
29
30   PUBLIC iom_nf90_open, iom_nf90_close, iom_nf90_varid, iom_nf90_get, iom_nf90_gettime, iom_nf90_rstput
31   PUBLIC iom_nf90_getatt
32
33   INTERFACE iom_nf90_get
34      MODULE PROCEDURE iom_nf90_g0d, iom_nf90_g123d
35   END INTERFACE
36   INTERFACE iom_nf90_getatt
37      MODULE PROCEDURE iom_nf90_intatt
38   END INTERFACE
39   INTERFACE iom_nf90_rstput
40      MODULE PROCEDURE iom_nf90_rp0123d
41   END INTERFACE
42
43   !!----------------------------------------------------------------------
44   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
45   !! $Id$
46   !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
47   !!----------------------------------------------------------------------
48
49CONTAINS
50
51   SUBROUTINE iom_nf90_open( cdname, kiomid, ldwrt, ldok, kdompar )
52      !!---------------------------------------------------------------------
53      !!                   ***  SUBROUTINE  iom_open  ***
54      !!
55      !! ** Purpose : open an input file with NF90
56      !!---------------------------------------------------------------------
57      CHARACTER(len=*)       , INTENT(inout)           ::   cdname      ! File name
58      INTEGER                , INTENT(  out)           ::   kiomid      ! nf90 identifier of the opened file
59      LOGICAL                , INTENT(in   )           ::   ldwrt       ! read or write the file?
60      LOGICAL                , INTENT(in   )           ::   ldok        ! check the existence
61      INTEGER, DIMENSION(2,5), INTENT(in   ), OPTIONAL ::   kdompar     ! domain parameters:
62
63      CHARACTER(LEN=256) ::   clinfo           ! info character
64      CHARACTER(LEN=256) ::   cltmp            ! temporary character
65      INTEGER            ::   iln              ! lengths of character
66      INTEGER            ::   istop            ! temporary storage of nstop
67      INTEGER            ::   if90id           ! nf90 identifier of the opened file
68      INTEGER            ::   idmy             ! dummy variable
69      INTEGER            ::   jl               ! loop variable
70      INTEGER            ::   ichunk           ! temporary storage of nn_chunksz
71      INTEGER            ::   imode            ! creation mode flag: NF90_CLOBBER or NF90_NOCLOBBER or NF90_HDF5
72      INTEGER            ::   ihdf5            ! local variable for retrieval of value for NF90_HDF5
73      LOGICAL            ::   llclobber        ! local definition of ln_clobber
74      !---------------------------------------------------------------------
75
76      clinfo = '                    iom_nf90_open ~~~  '
77      istop = nstop   ! store the actual value of nstop
78      IF( nn_chunksz > 0 ) THEN   ;   ichunk = nn_chunksz
79      ELSE                        ;   ichunk = NF90_SIZEHINT_DEFAULT
80      ENDIF
81      !
82      llclobber = ldwrt .AND. ln_clobber
83      IF( ldok .AND. .NOT. llclobber ) THEN      ! Open existing file...
84         !                 ! =============
85         IF( ldwrt ) THEN  ! ... in write mode
86            IF(lwp) WRITE(numout,*) TRIM(clinfo)//' open existing file: '//TRIM(cdname)//' in WRITE mode'
87            IF( snc4set%luse ) THEN
88               CALL iom_nf90_check(NF90_OPEN( TRIM(cdname), NF90_WRITE  , if90id ), clinfo)
89            ELSE
90               CALL iom_nf90_check(NF90_OPEN( TRIM(cdname), NF90_WRITE  , if90id, chunksize = ichunk ), clinfo)
91            ENDIF
92            CALL iom_nf90_check(NF90_SET_FILL( if90id, NF90_NOFILL, idmy                          ), clinfo)
93         ELSE              ! ... in read mode
94            IF(lwp) WRITE(numout,*) TRIM(clinfo)//' open existing file: '//TRIM(cdname)//' in READ mode'
95            CALL iom_nf90_check(NF90_OPEN( TRIM(cdname), NF90_NOWRITE, if90id, chunksize = ichunk ), clinfo)
96         ENDIF
97      ELSE                                       ! the file does not exist (or we overwrite it)
98         !                 ! =============
99         iln = INDEX( cdname, '.nc' )
100         IF( ldwrt ) THEN  ! the file should be open in write mode so we create it...
101            IF( jpnij > 1 ) THEN
102               WRITE(cltmp,'(a,a,i4.4,a)') cdname(1:iln-1), '_', narea-1, '.nc'
103               cdname = TRIM(cltmp)
104            ENDIF
105            IF(lwp) WRITE(numout,*) TRIM(clinfo)//' create new file: '//TRIM(cdname)//' in WRITE mode'
106
107            IF( llclobber ) THEN   ;   imode = IOR( NF90_64BIT_OFFSET, NF90_CLOBBER   )
108            ELSE                   ;   imode = IOR( NF90_64BIT_OFFSET, NF90_NOCLOBBER ) 
109            ENDIF
110            IF( snc4set%luse ) THEN
111               IF(lwp) WRITE(numout,*) TRIM(clinfo)//' creating file: '//TRIM(cdname)//' in hdf5 (netcdf4) mode'
112               CALL GET_NF90_SYMBOL("NF90_HDF5", ihdf5)
113               IF( llclobber ) THEN   ;   imode = IOR(ihdf5, NF90_CLOBBER)
114               ELSE                   ;   imode = IOR(ihdf5, NF90_NOCLOBBER)
115               ENDIF
116               CALL iom_nf90_check(NF90_CREATE( TRIM(cdname), imode, if90id ), clinfo)
117            ELSE
118               CALL iom_nf90_check(NF90_CREATE( TRIM(cdname), imode, if90id, chunksize = ichunk ), clinfo)
119            ENDIF
120            CALL iom_nf90_check(NF90_SET_FILL( if90id, NF90_NOFILL, idmy                     ), clinfo)
121            ! define dimensions
122            CALL iom_nf90_check(NF90_DEF_DIM( if90id, 'x', kdompar(1,1)  , idmy ), clinfo)
123            CALL iom_nf90_check(NF90_DEF_DIM( if90id, 'y', kdompar(2,1)  , idmy ), clinfo)
124            CALL iom_nf90_check(NF90_DEF_DIM( if90id, 'z', jpk           , idmy ), clinfo)
125            CALL iom_nf90_check(NF90_DEF_DIM( if90id, 't', NF90_UNLIMITED, idmy ), clinfo)
126            ! global attributes
127            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_number_total'   , jpnij              ), clinfo)
128            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_number'         , narea-1            ), clinfo)
129            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_dimensions_ids' , (/1     , 2     /) ), clinfo)
130            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_size_global'    , (/jpiglo, jpjglo/) ), clinfo)
131            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_size_local'     , kdompar(:,1)       ), clinfo)
132            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_position_first' , kdompar(:,2)       ), clinfo)
133            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_position_last'  , kdompar(:,3)       ), clinfo)
134            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_halo_size_start', kdompar(:,4)       ), clinfo)
135            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_halo_size_end'  , kdompar(:,5)       ), clinfo)
136            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_type'           , 'BOX'              ), clinfo)
137         ELSE              ! the file should be open for read mode so it must exist...
138            CALL ctl_stop( TRIM(clinfo), ' should be impossible case...' )
139         ENDIF
140      ENDIF
141      ! start to fill file informations
142      ! =============
143      IF( istop == nstop ) THEN   ! no error within this routine
144!does not work with some compilers         kiomid = MINLOC(iom_file(:)%nfid, dim = 1)
145         kiomid = 0
146         DO jl = jpmax_files, 1, -1
147            IF( iom_file(jl)%nfid == 0 )   kiomid = jl
148         ENDDO
149         iom_file(kiomid)%name   = TRIM(cdname)
150         iom_file(kiomid)%nfid   = if90id
151         iom_file(kiomid)%iolib  = jpnf90
152         iom_file(kiomid)%nvars  = 0
153         iom_file(kiomid)%irec   = -1   ! useless for NetCDF files, used to know if the file is in define mode
154         CALL iom_nf90_check(NF90_Inquire(if90id, unlimitedDimId = iom_file(kiomid)%iduld), clinfo)
155         IF ( iom_file(kiomid)%iduld .GE. 0 ) THEN
156           CALL iom_nf90_check(NF90_Inquire_Dimension(if90id, iom_file(kiomid)%iduld,   &
157        &                                               name = iom_file(kiomid)%uldname), clinfo)
158         ENDIF
159         IF(lwp) WRITE(numout,*) '                   ---> '//TRIM(cdname)//' OK'
160      ELSE
161         kiomid = 0               ! return error flag
162      ENDIF
163      !
164   END SUBROUTINE iom_nf90_open
165
166
167   SUBROUTINE iom_nf90_close( kiomid )
168      !!--------------------------------------------------------------------
169      !!                   ***  SUBROUTINE  iom_nf90_close  ***
170      !!
171      !! ** Purpose : close an input file with NF90
172      !!--------------------------------------------------------------------
173      INTEGER, INTENT(in) ::   kiomid   ! iom identifier of the file to be closed
174      CHARACTER(LEN=100)  ::   clinfo   ! info character
175      !---------------------------------------------------------------------
176      !
177      clinfo = '      iom_nf90_close    , file: '//TRIM(iom_file(kiomid)%name)
178      CALL iom_nf90_check(NF90_CLOSE(iom_file(kiomid)%nfid), clinfo)
179      !   
180   END SUBROUTINE iom_nf90_close
181
182
183   FUNCTION iom_nf90_varid ( kiomid, cdvar, kiv, kdimsz, kndims ) 
184      !!-----------------------------------------------------------------------
185      !!                  ***  FUNCTION  iom_varid  ***
186      !!
187      !! ** Purpose : get the id of a variable in a file with NF90
188      !!-----------------------------------------------------------------------
189      INTEGER              , INTENT(in   )           ::   kiomid   ! file Identifier
190      CHARACTER(len=*)     , INTENT(in   )           ::   cdvar    ! name of the variable
191      INTEGER              , INTENT(in   )           ::   kiv   !
192      INTEGER, DIMENSION(:), INTENT(  out), OPTIONAL ::   kdimsz   ! size of the dimensions
193      INTEGER,               INTENT(  out), OPTIONAL ::   kndims   ! size of the dimensions
194      !
195      INTEGER                        ::   iom_nf90_varid   ! iom variable Id
196      INTEGER                        ::   if90id           ! nf90 file identifier
197      INTEGER                        ::   ji               ! dummy loop index
198      INTEGER                        ::   ivarid           ! NetCDF  variable Id
199      INTEGER                        ::   i_nvd            ! number of dimension of the variable
200      INTEGER, DIMENSION(jpmax_dims) ::   idimid           ! dimension ids of the variable
201      LOGICAL                        ::   llok             ! ok  test
202      CHARACTER(LEN=100)             ::   clinfo           ! info character
203      !!-----------------------------------------------------------------------
204      clinfo = '          iom_nf90_varid, file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(cdvar)
205      iom_nf90_varid = 0                    ! default definition
206      IF( PRESENT(kdimsz) ) kdimsz(:) = 0   ! default definition
207      if90id = iom_file(kiomid)%nfid        ! get back NetCDF file id
208      !
209      llok = NF90_INQ_VARID( if90id, TRIM(cdvar), ivarid ) == nf90_noerr   ! does the variable exist in the file
210      IF( llok ) THEN
211         iom_nf90_varid = kiv
212         iom_file(kiomid)%nvars       = kiv
213         iom_file(kiomid)%nvid(kiv)   = ivarid
214         iom_file(kiomid)%cn_var(kiv) = TRIM(cdvar)
215         CALL iom_nf90_check(NF90_Inquire_Variable(if90id, ivarid, ndims = i_nvd), clinfo)   ! number of dimensions
216         iom_file(kiomid)%ndims(kiv)  = i_nvd
217         CALL iom_nf90_check(NF90_Inquire_Variable(if90id, ivarid, dimids = idimid(1:i_nvd)), clinfo)   ! dimensions ids
218         iom_file(kiomid)%luld(kiv) = .FALSE.   ! default value
219         iom_file(kiomid)%dimsz(:,kiv) = 0      ! reset dimsz in case previously used
220         DO ji = 1, i_nvd                       ! dimensions size
221            CALL iom_nf90_check(NF90_Inquire_Dimension(if90id, idimid(ji), len = iom_file(kiomid)%dimsz(ji,kiv)), clinfo)   
222            IF( idimid(ji) == iom_file(kiomid)%iduld ) iom_file(kiomid)%luld(kiv) = .TRUE.   ! unlimited dimension?
223         END DO
224         !---------- Deal with scale_factor and add_offset
225         llok = NF90_Inquire_attribute(if90id, ivarid, 'scale_factor') == nf90_noerr
226         IF( llok) THEN
227            CALL iom_nf90_check(NF90_GET_ATT(if90id, ivarid, 'scale_factor', iom_file(kiomid)%scf(kiv)), clinfo)
228         ELSE
229            iom_file(kiomid)%scf(kiv) = 1.
230         END IF
231         llok = NF90_Inquire_attribute(if90id, ivarid, 'add_offset') == nf90_noerr
232         IF( llok ) THEN
233            CALL iom_nf90_check(NF90_GET_ATT(if90id, ivarid, 'add_offset', iom_file(kiomid)%ofs(kiv)), clinfo)
234         ELSE
235            iom_file(kiomid)%ofs(kiv) = 0.
236         END IF
237         ! return the simension size
238         IF( PRESENT(kdimsz) ) THEN
239            IF( i_nvd == SIZE(kdimsz) ) THEN
240               kdimsz(:) = iom_file(kiomid)%dimsz(1:i_nvd,kiv)
241            ELSE
242               WRITE(ctmp1,*) i_nvd, SIZE(kdimsz)
243               CALL ctl_stop( TRIM(clinfo), 'error in kdimsz size'//TRIM(ctmp1) )
244            ENDIF
245         ENDIF
246         IF( PRESENT(kndims) )  kndims = iom_file(kiomid)%ndims(kiv)
247      ELSE 
248         iom_nf90_varid = -1   !   variable not found, return error code: -1
249      ENDIF
250      !
251   END FUNCTION iom_nf90_varid
252
253
254   SUBROUTINE iom_nf90_g0d( kiomid, kvid, pvar, kstart )
255      !!-----------------------------------------------------------------------
256      !!                  ***  ROUTINE  iom_nf90_g0d  ***
257      !!
258      !! ** Purpose : read a scalar with NF90
259      !!-----------------------------------------------------------------------
260      INTEGER ,               INTENT(in   )            ::   kiomid   ! Identifier of the file
261      INTEGER ,               INTENT(in   )            ::   kvid     ! variable id
262      REAL(wp),               INTENT(  out)            ::   pvar     ! read field
263      INTEGER , DIMENSION(1), INTENT(in   ), OPTIONAL  ::   kstart   ! start position of the reading in each axis
264      !
265      CHARACTER(LEN=100)      ::   clinfo   ! info character
266      !---------------------------------------------------------------------
267      clinfo = 'iom_nf90_g0d , file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(iom_file(kiomid)%cn_var(kvid))
268      CALL iom_nf90_check(NF90_GET_VAR(iom_file(kiomid)%nfid, iom_file(kiomid)%nvid(kvid), pvar, start = kstart), clinfo )
269      !
270   END SUBROUTINE iom_nf90_g0d
271
272
273   SUBROUTINE iom_nf90_g123d( kiomid, kvid, knbdim, kstart, kcount, kx1, kx2, ky1, ky2,   &
274         &                    pv_r1d, pv_r2d, pv_r3d )
275      !!-----------------------------------------------------------------------
276      !!                  ***  ROUTINE  iom_nf90_g123d  ***
277      !!
278      !! ** Purpose : read a 1D/2D/3D variable with NF90
279      !!
280      !! ** Method : read ONE record at each CALL
281      !!-----------------------------------------------------------------------
282      INTEGER                    , INTENT(in   )           ::   kiomid    ! iom identifier of the file
283      INTEGER                    , INTENT(in   )           ::   kvid      ! Name of the variable
284      INTEGER                    , INTENT(in   )           ::   knbdim    ! number of dimensions of the variable
285      INTEGER , DIMENSION(:)     , INTENT(in   )           ::   kstart    ! start position of the reading in each axis
286      INTEGER , DIMENSION(:)     , INTENT(in   )           ::   kcount    ! number of points to be read in each axis
287      INTEGER ,                    INTENT(in   )           ::   kx1, kx2, ky1, ky2   ! subdomain indexes
288      REAL(wp), DIMENSION(:)     , INTENT(  out), OPTIONAL ::   pv_r1d    ! read field (1D case)
289      REAL(wp), DIMENSION(:,:)   , INTENT(  out), OPTIONAL ::   pv_r2d    ! read field (2D case)
290      REAL(wp), DIMENSION(:,:,:) , INTENT(  out), OPTIONAL ::   pv_r3d    ! read field (3D case)
291      !
292      CHARACTER(LEN=100) ::   clinfo               ! info character
293      INTEGER            ::   if90id               ! nf90 identifier of the opened file
294      INTEGER            ::   ivid                 ! nf90 variable id
295      !---------------------------------------------------------------------
296      clinfo = 'iom_nf90_g123d , file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(iom_file(kiomid)%cn_var(kvid))
297      if90id = iom_file(kiomid)%nfid         ! get back NetCDF file id
298      ivid   = iom_file(kiomid)%nvid(kvid)   ! get back NetCDF var id
299      !
300      IF(     PRESENT(pv_r1d) ) THEN
301         CALL iom_nf90_check( NF90_GET_VAR(if90id, ivid, pv_r1d(:                ), start = kstart(1:knbdim),   &
302            &                                                                       count = kcount(1:knbdim)), clinfo )
303      ELSEIF( PRESENT(pv_r2d) ) THEN
304         CALL iom_nf90_check( NF90_GET_VAR(if90id, ivid, pv_r2d(kx1:kx2,ky1:ky2  ), start = kstart(1:knbdim),   &
305            &                                                                       count = kcount(1:knbdim)), clinfo )
306      ELSEIF( PRESENT(pv_r3d) ) THEN
307         CALL iom_nf90_check( NF90_GET_VAR(if90id, ivid, pv_r3d(kx1:kx2,ky1:ky2,:), start = kstart(1:knbdim),   &
308            &                                                                       count = kcount(1:knbdim)), clinfo )
309      ENDIF
310      !
311   END SUBROUTINE iom_nf90_g123d
312
313
314   SUBROUTINE iom_nf90_intatt( kiomid, cdatt, pvar )
315      !!-----------------------------------------------------------------------
316      !!                  ***  ROUTINE  iom_nf90_intatt  ***
317      !!
318      !! ** Purpose : read an integer attribute with NF90
319      !!-----------------------------------------------------------------------
320      INTEGER         , INTENT(in   ) ::   kiomid   ! Identifier of the file
321      CHARACTER(len=*), INTENT(in   ) ::   cdatt    ! attribute name
322      INTEGER         , INTENT(  out) ::   pvar     ! read field
323      !
324      INTEGER                         ::   if90id   ! temporary integer
325      LOGICAL                         ::   llok     ! temporary logical
326      CHARACTER(LEN=100)              ::   clinfo   ! info character
327      !---------------------------------------------------------------------
328      !
329      if90id = iom_file(kiomid)%nfid
330      llok = NF90_Inquire_attribute(if90id, NF90_GLOBAL, cdatt) == nf90_noerr
331      IF( llok) THEN
332         clinfo = 'iom_nf90_getatt, file: '//TRIM(iom_file(kiomid)%name)//', att: '//TRIM(cdatt)
333         CALL iom_nf90_check(NF90_GET_ATT(if90id, NF90_GLOBAL, cdatt, values=pvar), clinfo)
334      ELSE
335         CALL ctl_warn('iom_nf90_getatt: no attribute '//cdatt//' found')
336         pvar = -999
337      ENDIF
338      !
339   END SUBROUTINE iom_nf90_intatt
340
341
342   SUBROUTINE iom_nf90_gettime( kiomid, kvid, ptime, cdunits, cdcalendar )
343      !!--------------------------------------------------------------------
344      !!                   ***  SUBROUTINE iom_gettime  ***
345      !!
346      !! ** Purpose : read the time axis kvid in the file with NF90
347      !!--------------------------------------------------------------------
348      INTEGER                   , INTENT(in   ) ::   kiomid     ! file Identifier
349      INTEGER                   , INTENT(in   ) ::   kvid       ! variable id
350      REAL(wp), DIMENSION(:)    , INTENT(  out) ::   ptime      ! the time axis
351      CHARACTER(len=*), OPTIONAL, INTENT(  out) ::   cdunits    ! units attribute
352      CHARACTER(len=*), OPTIONAL, INTENT(  out) ::   cdcalendar ! calendar attribute
353      !
354      CHARACTER(LEN=100) ::   clinfo     ! info character
355      !---------------------------------------------------------------------
356      clinfo = 'iom_nf90_gettime, file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(iom_file(kiomid)%cn_var(kvid))
357      CALL iom_nf90_check(NF90_GET_VAR(iom_file(kiomid)%nfid, iom_file(kiomid)%nvid(kvid), ptime(:),   &
358            &                           start=(/ 1 /), count=(/ iom_file(kiomid)%dimsz(1, kvid) /)), clinfo)
359      IF ( PRESENT(cdunits) ) THEN
360         CALL iom_nf90_check(NF90_GET_ATT(iom_file(kiomid)%nfid, iom_file(kiomid)%nvid(kvid), "units", &
361            &                           values=cdunits), clinfo)
362      ENDIF
363      IF ( PRESENT(cdcalendar) ) THEN
364         CALL iom_nf90_check(NF90_GET_ATT(iom_file(kiomid)%nfid, iom_file(kiomid)%nvid(kvid), "calendar", &
365            &                           values=cdcalendar), clinfo)
366      ENDIF
367      !
368   END SUBROUTINE iom_nf90_gettime
369
370
371   SUBROUTINE iom_nf90_rp0123d( kt, kwrite, kiomid, cdvar , kvid  , ktype,   &
372         &                               pv_r0d, pv_r1d, pv_r2d, pv_r3d )
373      !!--------------------------------------------------------------------
374      !!                   ***  SUBROUTINE  iom_nf90_rstput  ***
375      !!
376      !! ** Purpose : read the time axis cdvar in the file
377      !!--------------------------------------------------------------------
378      INTEGER                     , INTENT(in)           ::   kt       ! ocean time-step
379      INTEGER                     , INTENT(in)           ::   kwrite   ! writing time-step
380      INTEGER                     , INTENT(in)           ::   kiomid   ! Identifier of the file
381      CHARACTER(len=*)            , INTENT(in)           ::   cdvar    ! variable name
382      INTEGER                     , INTENT(in)           ::   kvid     ! variable id
383      INTEGER                     , INTENT(in), OPTIONAL ::   ktype    ! variable type (default R8)
384      REAL(wp)                    , INTENT(in), OPTIONAL ::   pv_r0d   ! written Od field
385      REAL(wp), DIMENSION(      :), INTENT(in), OPTIONAL ::   pv_r1d   ! written 1d field
386      REAL(wp), DIMENSION(:, :   ), INTENT(in), OPTIONAL ::   pv_r2d   ! written 2d field
387      REAL(wp), DIMENSION(:, :, :), INTENT(in), OPTIONAL ::   pv_r3d   ! written 3d field
388      !
389      INTEGER               :: idims                ! number of dimension
390      INTEGER               :: idvar                ! variable id
391      INTEGER               :: jd                   ! dimension loop counter   
392      INTEGER               :: ix1, ix2, iy1, iy2   ! subdomain indexes   
393      INTEGER, DIMENSION(4) :: idimsz               ! dimensions size 
394      INTEGER, DIMENSION(4) :: idimid               ! dimensions id
395      CHARACTER(LEN=256)    :: clinfo               ! info character
396      CHARACTER(LEN= 12), DIMENSION(4) :: cltmp     ! temporary character
397      INTEGER               :: if90id               ! nf90 file identifier
398      INTEGER               :: idmy                 ! dummy variable
399      INTEGER               :: itype                ! variable type
400      INTEGER, DIMENSION(4) :: ichunksz             ! NetCDF4 chunk sizes. Will be computed using
401                                                    ! nn_nchunks_[i,j,k,t] namelist parameters
402      INTEGER               :: ichunkalg, ishuffle,&
403                               ideflate, ideflate_level
404                                                    ! NetCDF4 internally fixed parameters
405      LOGICAL               :: lchunk               ! logical switch to activate chunking and compression
406                                                    ! when appropriate (currently chunking is applied to 4d fields only)
407      !---------------------------------------------------------------------
408      !
409      clinfo = '          iom_nf90_rp0123d, file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(cdvar)
410      if90id = iom_file(kiomid)%nfid
411      !
412      ! define dimension variables if it is not already done
413      ! ==========================
414      IF( iom_file(kiomid)%nvars == 0 ) THEN
415         ! are we in define mode?
416         IF( iom_file(kiomid)%irec /= -1 ) THEN   ! trick: irec used to know if the file is in define mode or not
417            CALL iom_nf90_check(NF90_REDEF( if90id ), clinfo)   ;   iom_file(kiomid)%irec = -1
418         ENDIF
419         ! define the dimension variables if it is not already done
420         cltmp = (/ 'nav_lon     ', 'nav_lat     ', 'nav_lev     ', 'time_counter' /)
421         CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cltmp(1)), NF90_FLOAT , (/ 1, 2 /), iom_file(kiomid)%nvid(1) ), clinfo)
422         CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cltmp(2)), NF90_FLOAT , (/ 1, 2 /), iom_file(kiomid)%nvid(2) ), clinfo)
423         CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cltmp(3)), NF90_FLOAT , (/ 3    /), iom_file(kiomid)%nvid(3) ), clinfo)
424         CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cltmp(4)), NF90_DOUBLE, (/ 4    /), iom_file(kiomid)%nvid(4) ), clinfo)
425         ! update informations structure related the dimension variable we just added...
426         iom_file(kiomid)%nvars       = 4
427         iom_file(kiomid)%luld(1:4)   = (/ .FALSE., .FALSE., .FALSE., .TRUE. /)
428         iom_file(kiomid)%cn_var(1:4) = cltmp
429         iom_file(kiomid)%ndims(1:4)  = (/ 2, 2, 1, 1 /) 
430         ! trick: defined to 0 to say that dimension variables are defined but not yet written
431         iom_file(kiomid)%dimsz(1, 1)  = 0   
432         IF(lwp) WRITE(numout,*) TRIM(clinfo)//' define dimension variables done'
433      ENDIF
434      ! define the data if it is not already done
435      ! ===============
436      IF( kvid <= 0 ) THEN
437         !
438         ! NetCDF4 chunking and compression fixed settings
439         ichunkalg = 0
440         ishuffle = 1
441         ideflate = 1
442         ideflate_level = 1
443         !
444         idvar = iom_file(kiomid)%nvars + 1
445         ! are we in define mode?
446         IF( iom_file(kiomid)%irec /= -1 ) THEN   ! trick: irec used to know if the file is in define mode or not
447            CALL iom_nf90_check(NF90_REDEF( if90id ), clinfo)   ;   iom_file(kiomid)%irec = -1
448         ENDIF
449         ! variable definition
450         IF(     PRESENT(pv_r0d) ) THEN   ;   idims = 0
451         ELSEIF( PRESENT(pv_r1d) ) THEN   ;   idims = 2   ;   idimid(1:idims) = (/    3,4/)
452         ELSEIF( PRESENT(pv_r2d) ) THEN   ;   idims = 3   ;   idimid(1:idims) = (/1,2  ,4/)
453         ELSEIF( PRESENT(pv_r3d) ) THEN   ;   idims = 4   ;   idimid(1:idims) = (/1,2,3,4/)
454         ENDIF
455         IF( PRESENT(ktype) ) THEN   ! variable external type
456            SELECT CASE (ktype)
457            CASE (jp_r8)  ;   itype = NF90_DOUBLE
458            CASE (jp_r4)  ;   itype = NF90_FLOAT
459            CASE (jp_i4)  ;   itype = NF90_INT
460            CASE (jp_i2)  ;   itype = NF90_SHORT
461            CASE (jp_i1)  ;   itype = NF90_BYTE
462            CASE DEFAULT   ;   CALL ctl_stop( TRIM(clinfo)//' unknown variable type' )
463            END SELECT
464         ELSE
465            itype = NF90_DOUBLE
466         ENDIF
467         IF( PRESENT(pv_r0d) ) THEN
468            CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cdvar), itype,                    &
469                 &                            iom_file(kiomid)%nvid(idvar) ), clinfo)
470         ELSE
471            CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cdvar), itype, idimid(1:idims),   &
472                 &                            iom_file(kiomid)%nvid(idvar) ), clinfo)
473         ENDIF
474         lchunk = .false.
475         IF( snc4set%luse .AND. idims.eq.4 ) lchunk = .true.
476         ! update informations structure related the new variable we want to add...
477         iom_file(kiomid)%nvars         = idvar
478         iom_file(kiomid)%cn_var(idvar) = TRIM(cdvar)
479         iom_file(kiomid)%scf(idvar)    = 1.
480         iom_file(kiomid)%ofs(idvar)    = 0.
481         iom_file(kiomid)%ndims(idvar)  = idims
482         IF( .NOT. PRESENT(pv_r0d) ) THEN   ;   iom_file(kiomid)%luld(idvar) = .TRUE.
483         ELSE                               ;   iom_file(kiomid)%luld(idvar) = .FALSE.
484         ENDIF
485         DO jd = 1, idims
486            CALL iom_nf90_check(NF90_INQUIRE_DIMENSION( if90id, idimid(jd), len = iom_file(kiomid)%dimsz(jd,idvar) ), clinfo)
487            IF ( lchunk ) ichunksz(jd) = iom_file(kiomid)%dimsz(jd,idvar)
488         END DO
489         IF ( lchunk ) THEN
490            ! Calculate chunk sizes by partitioning each dimension as requested in namnc4 namelist
491            ! Disallow very small chunk sizes and prevent chunk sizes larger than each individual dimension
492            ichunksz(1) = MIN( ichunksz(1),MAX( (ichunksz(1)-1)/snc4set%ni + 1 ,16 ) ) ! Suggested default nc4set%ni=4
493            ichunksz(2) = MIN( ichunksz(2),MAX( (ichunksz(2)-1)/snc4set%nj + 1 ,16 ) ) ! Suggested default nc4set%nj=2
494            ichunksz(3) = MIN( ichunksz(3),MAX( (ichunksz(3)-1)/snc4set%nk + 1 , 1 ) ) ! Suggested default nc4set%nk=6
495            ichunksz(4) = 1                                                            ! Do not allow chunks to span the
496                                                                                       ! unlimited dimension
497            CALL iom_nf90_check(SET_NF90_DEF_VAR_CHUNKING(if90id, idvar, ichunkalg, ichunksz), clinfo)
498            CALL iom_nf90_check(SET_NF90_DEF_VAR_DEFLATE(if90id, idvar, ishuffle, ideflate, ideflate_level), clinfo)
499            IF(lwp) WRITE(numout,*) TRIM(clinfo)//' chunked ok. Chunks sizes: ', ichunksz
500         ENDIF
501         IF(lwp) WRITE(numout,*) TRIM(clinfo)//' defined ok'
502      ELSE
503         idvar = kvid
504      ENDIF
505
506      ! time step kwrite : write the variable
507      IF( kt == kwrite ) THEN
508         ! are we in write mode?
509         IF( iom_file(kiomid)%irec == -1 ) THEN   ! trick: irec used to know if the file is in define mode or not
510            CALL iom_nf90_check(NF90_ENDDEF( if90id ), clinfo)   ;   iom_file(kiomid)%irec = 0
511         ENDIF
512         ! on what kind of domain must the data be written?
513         IF( PRESENT(pv_r2d) .OR. PRESENT(pv_r3d) ) THEN
514            idimsz(1:2) = iom_file(kiomid)%dimsz(1:2,idvar)
515            IF(     idimsz(1) == (nlei - nldi + 1) .AND. idimsz(2) == (nlej - nldj + 1) ) THEN
516               ix1 = nldi   ;   ix2 = nlei   ;   iy1 = nldj   ;   iy2 = nlej
517            ELSEIF( idimsz(1) == nlci              .AND. idimsz(2) == nlcj              ) THEN
518               ix1 = 1      ;   ix2 = nlci   ;   iy1 = 1      ;   iy2 = nlcj
519            ELSEIF( idimsz(1) == jpi               .AND. idimsz(2) == jpj               ) THEN
520               ix1 = 1      ;   ix2 = jpi    ;   iy1 = 1      ;   iy2 = jpj
521            ELSE
522               CALL ctl_stop( 'iom_nf90_rp0123d: should have been an impossible case...' )
523            ENDIF
524
525            ! write dimension variables if it is not already done
526            ! =============
527            ! trick: is defined to 0 => dimension variable are defined but not yet written
528            IF( iom_file(kiomid)%dimsz(1, 1) == 0 ) THEN
529               CALL iom_nf90_check(NF90_INQ_VARID( if90id, 'nav_lon'     , idmy ), clinfo)
530               CALL iom_nf90_check(NF90_PUT_VAR( if90id, idmy, glamt(ix1:ix2, iy1:iy2) ), clinfo)
531               CALL iom_nf90_check(NF90_INQ_VARID( if90id, 'nav_lat'     , idmy ), clinfo)
532               CALL iom_nf90_check(NF90_PUT_VAR( if90id, idmy, gphit(ix1:ix2, iy1:iy2) ), clinfo)
533               CALL iom_nf90_check(NF90_INQ_VARID( if90id, 'nav_lev'     , idmy ), clinfo)
534               CALL iom_nf90_check(NF90_PUT_VAR( if90id, idmy, gdept_1d                ), clinfo)
535               ! +++ WRONG VALUE: to be improved but not really useful...
536               CALL iom_nf90_check(NF90_INQ_VARID( if90id, 'time_counter', idmy ), clinfo)
537               CALL iom_nf90_check(NF90_PUT_VAR( if90id, idmy, kt                      ), clinfo)   
538               ! update the values of the variables dimensions size
539               CALL iom_nf90_check(NF90_INQUIRE_DIMENSION( if90id, 1, len = iom_file(kiomid)%dimsz(1,1) ), clinfo)
540               CALL iom_nf90_check(NF90_INQUIRE_DIMENSION( if90id, 2, len = iom_file(kiomid)%dimsz(2,1) ), clinfo)
541               iom_file(kiomid)%dimsz(1:2, 2) = iom_file(kiomid)%dimsz(1:2, 1)
542               CALL iom_nf90_check(NF90_INQUIRE_DIMENSION( if90id, 3, len = iom_file(kiomid)%dimsz(1,3) ), clinfo)
543               iom_file(kiomid)%dimsz(1  , 4) = 1   ! unlimited dimension
544               IF(lwp) WRITE(numout,*) TRIM(clinfo)//' write dimension variables done'
545            ENDIF
546         ENDIF
547
548         ! write the data
549         ! =============
550         IF(     PRESENT(pv_r0d) ) THEN
551            CALL iom_nf90_check(NF90_PUT_VAR( if90id, idvar, pv_r0d                      ), clinfo)
552         ELSEIF( PRESENT(pv_r1d) ) THEN
553            CALL iom_nf90_check(NF90_PUT_VAR( if90id, idvar, pv_r1d(                  :) ), clinfo)
554         ELSEIF( PRESENT(pv_r2d) ) THEN
555            CALL iom_nf90_check(NF90_PUT_VAR( if90id, idvar, pv_r2d(ix1:ix2, iy1:iy2   ) ), clinfo)
556         ELSEIF( PRESENT(pv_r3d) ) THEN
557            CALL iom_nf90_check(NF90_PUT_VAR( if90id, idvar, pv_r3d(ix1:ix2, iy1:iy2, :) ), clinfo)
558         ENDIF
559         ! add 1 to the size of the temporal dimension (not really useful...)
560         IF( iom_file(kiomid)%luld(idvar) )   iom_file(kiomid)%dimsz(iom_file(kiomid)%ndims(idvar), idvar)    &
561               &                            = iom_file(kiomid)%dimsz(iom_file(kiomid)%ndims(idvar), idvar) + 1
562         IF(lwp) WRITE(numout,*) TRIM(clinfo)//' written ok'
563      ENDIF
564      !     
565   END SUBROUTINE iom_nf90_rp0123d
566
567
568   SUBROUTINE iom_nf90_check( kstatus, cdinfo )
569      !!--------------------------------------------------------------------
570      !!                   ***  SUBROUTINE iom_nf90_check  ***
571      !!
572      !! ** Purpose :   check nf90 errors
573      !!--------------------------------------------------------------------
574      INTEGER,          INTENT(in) :: kstatus
575      CHARACTER(LEN=*), INTENT(in) :: cdinfo
576      !---------------------------------------------------------------------
577      IF(kstatus /= nf90_noerr)   CALL ctl_stop( 'iom_nf90_check : '//TRIM(nf90_strerror(kstatus)), TRIM(cdinfo) )
578   END SUBROUTINE iom_nf90_check
579
580   !!======================================================================
581END MODULE iom_nf90
Note: See TracBrowser for help on using the repository browser.