source: NEMO/trunk/src/OCE/IOM/iom_nf90.F90 @ 12377

Last change on this file since 12377 was 12377, checked in by acc, 6 months ago

The big one. Merging all 2019 developments from the option 1 branch back onto the trunk.

This changeset reproduces 2019/dev_r11943_MERGE_2019 on the trunk using a 2-URL merge
onto a working copy of the trunk. I.e.:

svn merge —ignore-ancestry \

svn+ssh://acc@forge.ipsl.jussieu.fr/ipsl/forge/projets/nemo/svn/NEMO/trunk \
svn+ssh://acc@forge.ipsl.jussieu.fr/ipsl/forge/projets/nemo/svn/NEMO/branches/2019/dev_r11943_MERGE_2019 ./

The —ignore-ancestry flag avoids problems that may otherwise arise from the fact that
the merge history been trunk and branch may have been applied in a different order but
care has been taken before this step to ensure that all applicable fixes and updates
are present in the merge branch.

The trunk state just before this step has been branched to releases/release-4.0-HEAD
and that branch has been immediately tagged as releases/release-4.0.2. Any fixes
or additions in response to tickets on 4.0, 4.0.1 or 4.0.2 should be done on
releases/release-4.0-HEAD. From now on future 'point' releases (e.g. 4.0.2) will
remain unchanged with periodic releases as needs demand. Note release-4.0-HEAD is a
transitional naming convention. Future full releases, say 4.2, will have a release-4.2
branch which fulfills this role and the first point release (e.g. 4.2.0) will be made
immediately following the release branch creation.

2020 developments can be started from any trunk revision later than this one.

  • Property svn:keywords set to Id
File size: 44.2 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   !!            3.6  ! 2015-15  (J. Harle) Added procedure to read REAL attributes
10   !!            4.0  ! 2017-11 (M. Andrejczuk) Extend IOM interface to write any 3D fields
11   !!----------------------------------------------------------------------
12
13   !!----------------------------------------------------------------------
14   !!   iom_open       : open a file read only
15   !!   iom_close      : close a file or all files opened by iom
16   !!   iom_get        : read a field (interfaced to several routines)
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 sbc_oce, ONLY: jpka, ght_abl ! abl vertical level number and height
22   USE lbclnk          ! lateal boundary condition / mpp exchanges
23   USE iom_def         ! iom variables definitions
24   USE netcdf          ! NetCDF library
25   USE in_out_manager  ! I/O manager
26   USE lib_mpp         ! MPP library
27
28   IMPLICIT NONE
29   PRIVATE
30
31   PUBLIC iom_nf90_open  , iom_nf90_close, iom_nf90_varid, iom_nf90_get, iom_nf90_rstput
32   PUBLIC iom_nf90_chkatt, iom_nf90_getatt, iom_nf90_putatt
33
34   INTERFACE iom_nf90_get
35      MODULE PROCEDURE iom_nf90_g0d, iom_nf90_g123d
36   END INTERFACE
37   INTERFACE iom_nf90_rstput
38      MODULE PROCEDURE iom_nf90_rp0123d
39   END INTERFACE
40
41   !!----------------------------------------------------------------------
42   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
43   !! $Id$
44   !! Software governed by the CeCILL license (see ./LICENSE)
45   !!----------------------------------------------------------------------
46CONTAINS
47
48   SUBROUTINE iom_nf90_open( cdname, kiomid, ldwrt, ldok, kdompar, kdlev )
49      !!---------------------------------------------------------------------
50      !!                   ***  SUBROUTINE  iom_open  ***
51      !!
52      !! ** Purpose : open an input file with NF90
53      !!---------------------------------------------------------------------
54      CHARACTER(len=*)       , INTENT(inout)           ::   cdname      ! File name
55      INTEGER                , INTENT(  out)           ::   kiomid      ! nf90 identifier of the opened file
56      LOGICAL                , INTENT(in   )           ::   ldwrt       ! read or write the file?
57      LOGICAL                , INTENT(in   )           ::   ldok        ! check the existence
58      INTEGER, DIMENSION(2,5), INTENT(in   ), OPTIONAL ::   kdompar     ! domain parameters:
59      INTEGER                , INTENT(in   ), OPTIONAL ::   kdlev       ! size of the ice/abl third dimension
60
61      CHARACTER(LEN=256) ::   clinfo           ! info character
62      CHARACTER(LEN=256) ::   cltmp            ! temporary character
63      INTEGER            ::   iln              ! lengths of character
64      INTEGER            ::   istop            ! temporary storage of nstop
65      INTEGER            ::   if90id           ! nf90 identifier of the opened file
66      INTEGER            ::   idmy             ! dummy variable
67      INTEGER            ::   jl               ! loop variable
68      INTEGER            ::   ichunk           ! temporary storage of nn_chunksz
69      INTEGER            ::   imode            ! creation mode flag: NF90_CLOBBER or NF90_NOCLOBBER or NF90_HDF5
70      INTEGER            ::   ihdf5            ! local variable for retrieval of value for NF90_HDF5
71      LOGICAL            ::   llclobber        ! local definition of ln_clobber
72      INTEGER            ::   ilevels          ! vertical levels
73      !---------------------------------------------------------------------
74      !
75      clinfo = '                    iom_nf90_open ~~~  '
76      istop = nstop     ! store the actual value of nstop
77      !
78      !                 !number of vertical levels
79      IF( PRESENT(kdlev) )   THEN   ;   ilevels = kdlev    ! use input value (useful for sea-ice and abl)
80      ELSE                          ;   ilevels = jpk      ! by default jpk
81      ENDIF
82      !
83      IF( nn_chunksz > 0 ) THEN   ;   ichunk = nn_chunksz
84      ELSE                        ;   ichunk = NF90_SIZEHINT_DEFAULT
85      ENDIF
86      !
87      llclobber = ldwrt .AND. ln_clobber
88      IF( ldok .AND. .NOT. llclobber ) THEN      !==  Open existing file ==!
89         !                                       !=========================!
90         IF( ldwrt ) THEN  ! ... in write mode
91            IF(lwp) WRITE(numout,*) TRIM(clinfo)//' open existing file: '//TRIM(cdname)//' in WRITE mode'
92            IF( snc4set%luse ) THEN
93               CALL iom_nf90_check(NF90_OPEN( TRIM(cdname), NF90_WRITE  , if90id ), clinfo)
94            ELSE
95               CALL iom_nf90_check(NF90_OPEN( TRIM(cdname), NF90_WRITE  , if90id, chunksize = ichunk ), clinfo)
96            ENDIF
97            CALL iom_nf90_check(NF90_SET_FILL( if90id, NF90_NOFILL, idmy                          ), clinfo)
98         ELSE              ! ... in read mode
99            IF(lwp) WRITE(numout,*) TRIM(clinfo)//' open existing file: '//TRIM(cdname)//' in READ mode'
100            CALL iom_nf90_check(NF90_OPEN( TRIM(cdname), NF90_NOWRITE, if90id, chunksize = ichunk ), clinfo)
101         ENDIF
102      ELSE                                       !== the file doesn't exist ==!   (or we overwrite it)
103         !                                       !============================!
104         iln = INDEX( cdname, '.nc' )
105         IF( ldwrt ) THEN              !* the file should be open in write mode so we create it...
106            IF( jpnij > 1 ) THEN
107               WRITE(cltmp,'(a,a,i4.4,a)') cdname(1:iln-1), '_', narea-1, '.nc'
108               cdname = TRIM(cltmp)
109            ENDIF
110            IF(lwp) WRITE(numout,*) TRIM(clinfo)//' create new file: '//TRIM(cdname)//' in WRITE mode'
111
112            IF( llclobber ) THEN   ;   imode = IOR( NF90_64BIT_OFFSET, NF90_CLOBBER   )
113            ELSE                   ;   imode = IOR( NF90_64BIT_OFFSET, NF90_NOCLOBBER ) 
114            ENDIF
115            IF( snc4set%luse ) THEN
116               IF(lwp) WRITE(numout,*) TRIM(clinfo)//' creating file: '//TRIM(cdname)//' in hdf5 (netcdf4) mode'
117               CALL GET_NF90_SYMBOL("NF90_HDF5", ihdf5)
118               IF( llclobber ) THEN   ;   imode = IOR(ihdf5, NF90_CLOBBER)
119               ELSE                   ;   imode = IOR(ihdf5, NF90_NOCLOBBER)
120               ENDIF
121               CALL iom_nf90_check(NF90_CREATE( TRIM(cdname), imode, if90id ), clinfo)
122            ELSE
123               CALL iom_nf90_check(NF90_CREATE( TRIM(cdname), imode, if90id, chunksize = ichunk ), clinfo)
124            ENDIF
125            CALL iom_nf90_check(NF90_SET_FILL( if90id, NF90_NOFILL,                   idmy ), clinfo)
126            ! define dimensions
127            CALL iom_nf90_check(NF90_DEF_DIM( if90id,            'x',   kdompar(1,1), idmy ), clinfo)
128            CALL iom_nf90_check(NF90_DEF_DIM( if90id,            'y',   kdompar(2,1), idmy ), clinfo)
129            IF( PRESENT(kdlev) ) THEN
130              IF( kdlev == jpka ) THEN
131                 CALL iom_nf90_check(NF90_DEF_DIM( if90id, 'nav_lev',          kdlev, idmy ), clinfo)
132                 CALL iom_nf90_check(NF90_DEF_DIM( if90id, 'time_counter', NF90_UNLIMITED, idmy ), clinfo)
133              ELSE
134                 CALL iom_nf90_check(NF90_DEF_DIM( if90id, 'nav_lev',            jpk, idmy ), clinfo)
135                 CALL iom_nf90_check(NF90_DEF_DIM( if90id, 'time_counter', NF90_UNLIMITED, idmy ), clinfo)
136                 CALL iom_nf90_check(NF90_DEF_DIM( if90id,  'numcat',          kdlev, idmy ), clinfo)
137              ENDIF
138            ELSE
139               CALL iom_nf90_check(NF90_DEF_DIM( if90id, 'nav_lev',            jpk, idmy ), clinfo)
140               CALL iom_nf90_check(NF90_DEF_DIM( if90id, 'time_counter', NF90_UNLIMITED, idmy ), clinfo)
141            ENDIF
142            ! global attributes
143            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_number_total'   , jpnij              ), clinfo)
144            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_number'         , narea-1            ), clinfo)
145            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_dimensions_ids' , (/1     , 2     /) ), clinfo)
146            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_size_global'    , (/jpiglo, jpjglo/) ), clinfo)
147            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_size_local'     , kdompar(:,1)       ), clinfo)
148            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_position_first' , kdompar(:,2)       ), clinfo)
149            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_position_last'  , kdompar(:,3)       ), clinfo)
150            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_halo_size_start', kdompar(:,4)       ), clinfo)
151            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_halo_size_end'  , kdompar(:,5)       ), clinfo)
152            CALL iom_nf90_check(NF90_PUT_ATT( if90id, NF90_GLOBAL, 'DOMAIN_type'           , 'BOX'              ), clinfo)
153         ELSE                          !* the file should be open for read mode so it must exist...
154            CALL ctl_stop( TRIM(clinfo), ' should be impossible case...' )
155         ENDIF
156      ENDIF
157      !
158      ! start to fill file informations
159      ! =============
160      IF( istop == nstop ) THEN   ! no error within this routine
161!does not work with some compilers         kiomid = MINLOC(iom_file(:)%nfid, dim = 1)
162         kiomid = 0
163         DO jl = jpmax_files, 1, -1
164            IF( iom_file(jl)%nfid == 0 )   kiomid = jl
165         ENDDO
166         iom_file(kiomid)%name   = TRIM(cdname)
167         iom_file(kiomid)%nfid   = if90id
168         iom_file(kiomid)%nvars  = 0
169         iom_file(kiomid)%irec   = -1   ! useless for NetCDF files, used to know if the file is in define mode
170         iom_file(kiomid)%nlev   = ilevels
171         CALL iom_nf90_check(NF90_Inquire(if90id, unlimitedDimId = iom_file(kiomid)%iduld), clinfo)
172         IF( iom_file(kiomid)%iduld .GE. 0 ) THEN
173            CALL iom_nf90_check(NF90_Inquire_Dimension(if90id, iom_file(kiomid)%iduld,    & 
174               &                                       name = iom_file(kiomid)%uldname,   &
175               &                                       len  = iom_file(kiomid)%lenuld ), clinfo )
176         ENDIF
177         IF(lwp) WRITE(numout,*) '                   ---> '//TRIM(cdname)//' OK'
178      ELSE
179         kiomid = 0               ! return error flag
180      ENDIF
181      !
182   END SUBROUTINE iom_nf90_open
183
184
185   SUBROUTINE iom_nf90_close( kiomid )
186      !!--------------------------------------------------------------------
187      !!                   ***  SUBROUTINE  iom_nf90_close  ***
188      !!
189      !! ** Purpose : close an input file with NF90
190      !!--------------------------------------------------------------------
191      INTEGER, INTENT(in) ::   kiomid   ! iom identifier of the file to be closed
192      CHARACTER(LEN=100)  ::   clinfo   ! info character
193      !---------------------------------------------------------------------
194      clinfo = '      iom_nf90_close    , file: '//TRIM(iom_file(kiomid)%name)
195      CALL iom_nf90_check(NF90_CLOSE(iom_file(kiomid)%nfid), clinfo)
196   END SUBROUTINE iom_nf90_close
197
198
199   FUNCTION iom_nf90_varid ( kiomid, cdvar, kiv, kdimsz, kndims, lduld ) 
200      !!-----------------------------------------------------------------------
201      !!                  ***  FUNCTION  iom_varid  ***
202      !!
203      !! ** Purpose : get the id of a variable in a file with NF90
204      !!-----------------------------------------------------------------------
205      INTEGER              , INTENT(in   )           ::   kiomid   ! file Identifier
206      CHARACTER(len=*)     , INTENT(in   )           ::   cdvar    ! name of the variable
207      INTEGER              , INTENT(in   )           ::   kiv   !
208      INTEGER, DIMENSION(:), INTENT(  out), OPTIONAL ::   kdimsz   ! size of each dimension
209      INTEGER              , INTENT(  out), OPTIONAL ::   kndims   ! number of dimensions
210      LOGICAL              , INTENT(  out), OPTIONAL ::   lduld    ! true if the last dimension is unlimited (time)
211      !
212      INTEGER                        ::   iom_nf90_varid   ! iom variable Id
213      INTEGER                        ::   if90id           ! nf90 file identifier
214      INTEGER                        ::   ji               ! dummy loop index
215      INTEGER                        ::   ivarid           ! NetCDF  variable Id
216      INTEGER                        ::   i_nvd            ! number of dimension of the variable
217      INTEGER, DIMENSION(jpmax_dims) ::   idimid           ! dimension ids of the variable
218      LOGICAL                        ::   llok             ! ok  test
219      CHARACTER(LEN=100)             ::   clinfo           ! info character
220      !!-----------------------------------------------------------------------
221      clinfo = '          iom_nf90_varid, file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(cdvar)
222      iom_nf90_varid = 0                    ! default definition
223      IF( PRESENT(kdimsz) ) kdimsz(:) = 0   ! default definition
224      if90id = iom_file(kiomid)%nfid        ! get back NetCDF file id
225      !
226      llok = NF90_INQ_VARID( if90id, TRIM(cdvar), ivarid ) == nf90_noerr   ! does the variable exist in the file
227      IF( llok ) THEN
228         iom_nf90_varid = kiv
229         iom_file(kiomid)%nvars       = kiv
230         iom_file(kiomid)%nvid(kiv)   = ivarid
231         iom_file(kiomid)%cn_var(kiv) = TRIM(cdvar)
232         CALL iom_nf90_check(NF90_Inquire_Variable(if90id, ivarid, ndims = i_nvd), clinfo)   ! number of dimensions
233         iom_file(kiomid)%ndims(kiv)  = i_nvd
234         CALL iom_nf90_check(NF90_Inquire_Variable(if90id, ivarid, dimids = idimid(1:i_nvd)), clinfo)   ! dimensions ids
235         iom_file(kiomid)%luld(kiv) = .FALSE.   ! default value
236         iom_file(kiomid)%dimsz(:,kiv) = 0      ! reset dimsz in case previously used
237         DO ji = 1, i_nvd                       ! dimensions size
238            CALL iom_nf90_check(NF90_Inquire_Dimension(if90id, idimid(ji), len = iom_file(kiomid)%dimsz(ji,kiv)), clinfo)   
239            IF( idimid(ji) == iom_file(kiomid)%iduld ) iom_file(kiomid)%luld(kiv) = .TRUE.   ! unlimited dimension?
240         END DO
241         !---------- Deal with scale_factor and add_offset
242         llok = NF90_Inquire_attribute(if90id, ivarid, 'scale_factor') == nf90_noerr
243         IF( llok) THEN
244            CALL iom_nf90_check(NF90_GET_ATT(if90id, ivarid, 'scale_factor', iom_file(kiomid)%scf(kiv)), clinfo)
245         ELSE
246            iom_file(kiomid)%scf(kiv) = 1.
247         END IF
248         llok = NF90_Inquire_attribute(if90id, ivarid, 'add_offset') == nf90_noerr
249         IF( llok ) THEN
250            CALL iom_nf90_check(NF90_GET_ATT(if90id, ivarid, 'add_offset', iom_file(kiomid)%ofs(kiv)), clinfo)
251         ELSE
252            iom_file(kiomid)%ofs(kiv) = 0.
253         END IF
254         ! return the simension size
255         IF( PRESENT(kdimsz) ) THEN
256            IF( i_nvd <= SIZE(kdimsz) ) THEN
257               kdimsz(1:i_nvd) = iom_file(kiomid)%dimsz(1:i_nvd,kiv)
258            ELSE
259               WRITE(ctmp1,*) i_nvd, SIZE(kdimsz)
260               CALL ctl_stop( TRIM(clinfo), 'error in kdimsz size'//TRIM(ctmp1) )
261            ENDIF
262         ENDIF
263         IF( PRESENT(kndims) )  kndims = iom_file(kiomid)%ndims(kiv)
264         IF( PRESENT( lduld) )  lduld  = iom_file(kiomid)%luld(kiv)
265      ELSE 
266         iom_nf90_varid = -1   !   variable not found, return error code: -1
267      ENDIF
268      !
269   END FUNCTION iom_nf90_varid
270
271   !!----------------------------------------------------------------------
272   !!                   INTERFACE iom_nf90_get
273   !!----------------------------------------------------------------------
274
275   SUBROUTINE iom_nf90_g0d( kiomid, kvid, pvar, kstart )
276      !!-----------------------------------------------------------------------
277      !!                  ***  ROUTINE  iom_nf90_g0d  ***
278      !!
279      !! ** Purpose : read a scalar with NF90
280      !!-----------------------------------------------------------------------
281      INTEGER ,               INTENT(in   )            ::   kiomid   ! Identifier of the file
282      INTEGER ,               INTENT(in   )            ::   kvid     ! variable id
283      REAL(wp),               INTENT(  out)            ::   pvar     ! read field
284      INTEGER , DIMENSION(1), INTENT(in   ), OPTIONAL  ::   kstart   ! start position of the reading in each axis
285      !
286      CHARACTER(LEN=100)      ::   clinfo   ! info character
287      !---------------------------------------------------------------------
288      clinfo = 'iom_nf90_g0d , file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(iom_file(kiomid)%cn_var(kvid))
289      CALL iom_nf90_check(NF90_GET_VAR(iom_file(kiomid)%nfid, iom_file(kiomid)%nvid(kvid), pvar, start = kstart), clinfo )
290   END SUBROUTINE iom_nf90_g0d
291
292
293   SUBROUTINE iom_nf90_g123d( kiomid, kvid, knbdim, kstart, kcount, kx1, kx2, ky1, ky2,   &
294         &                    pv_r1d, pv_r2d, pv_r3d )
295      !!-----------------------------------------------------------------------
296      !!                  ***  ROUTINE  iom_nf90_g123d  ***
297      !!
298      !! ** Purpose : read a 1D/2D/3D variable with NF90
299      !!
300      !! ** Method : read ONE record at each CALL
301      !!-----------------------------------------------------------------------
302      INTEGER                    , INTENT(in   )           ::   kiomid    ! iom identifier of the file
303      INTEGER                    , INTENT(in   )           ::   kvid      ! Name of the variable
304      INTEGER                    , INTENT(in   )           ::   knbdim    ! number of dimensions of the variable
305      INTEGER , DIMENSION(:)     , INTENT(in   )           ::   kstart    ! start position of the reading in each axis
306      INTEGER , DIMENSION(:)     , INTENT(in   )           ::   kcount    ! number of points to be read in each axis
307      INTEGER ,                    INTENT(in   )           ::   kx1, kx2, ky1, ky2   ! subdomain indexes
308      REAL(wp), DIMENSION(:)     , INTENT(  out), OPTIONAL ::   pv_r1d    ! read field (1D case)
309      REAL(wp), DIMENSION(:,:)   , INTENT(  out), OPTIONAL ::   pv_r2d    ! read field (2D case)
310      REAL(wp), DIMENSION(:,:,:) , INTENT(  out), OPTIONAL ::   pv_r3d    ! read field (3D case)
311      !
312      CHARACTER(LEN=100) ::   clinfo               ! info character
313      INTEGER            ::   if90id               ! nf90 identifier of the opened file
314      INTEGER            ::   ivid                 ! nf90 variable id
315      !---------------------------------------------------------------------
316      clinfo = 'iom_nf90_g123d , file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(iom_file(kiomid)%cn_var(kvid))
317      if90id = iom_file(kiomid)%nfid         ! get back NetCDF file id
318      ivid   = iom_file(kiomid)%nvid(kvid)   ! get back NetCDF var id
319      !
320      IF(     PRESENT(pv_r1d) ) THEN
321         CALL iom_nf90_check( NF90_GET_VAR(if90id, ivid, pv_r1d(:                ), start = kstart(1:knbdim),   &
322            &                                                                       count = kcount(1:knbdim)), clinfo )
323      ELSEIF( PRESENT(pv_r2d) ) THEN
324         CALL iom_nf90_check( NF90_GET_VAR(if90id, ivid, pv_r2d(kx1:kx2,ky1:ky2  ), start = kstart(1:knbdim),   &
325            &                                                                       count = kcount(1:knbdim)), clinfo )
326      ELSEIF( PRESENT(pv_r3d) ) THEN
327         CALL iom_nf90_check( NF90_GET_VAR(if90id, ivid, pv_r3d(kx1:kx2,ky1:ky2,:), start = kstart(1:knbdim),   &
328            &                                                                       count = kcount(1:knbdim)), clinfo )
329      ENDIF
330      !
331   END SUBROUTINE iom_nf90_g123d
332
333
334   SUBROUTINE iom_nf90_chkatt( kiomid, cdatt, llok, ksize, cdvar )
335      !!-----------------------------------------------------------------------
336      !!                  ***  ROUTINE  iom_nf90_chkatt  ***
337      !!
338      !! ** Purpose : check existence of attribute with NF90
339      !!              (either a global attribute (default) or a variable
340      !!               attribute if optional variable name is supplied (cdvar))
341      !!-----------------------------------------------------------------------
342      INTEGER         , INTENT(in   ) ::   kiomid   ! Identifier of the file
343      CHARACTER(len=*), INTENT(in   ) ::   cdatt    ! attribute name
344      LOGICAL         , INTENT(  out) ::   llok     ! error code
345      INTEGER         , INTENT(  out), OPTIONAL     &
346                      &               ::   ksize    ! attribute size
347      CHARACTER(len=*), INTENT(in   ), OPTIONAL     &
348                      &               ::   cdvar    ! name of the variable
349      !
350      INTEGER                         ::   if90id   ! temporary integer
351      INTEGER                         ::   isize    ! temporary integer
352      INTEGER                         ::   ivarid   ! NetCDF variable Id
353      !---------------------------------------------------------------------
354      !
355      if90id = iom_file(kiomid)%nfid
356      IF( PRESENT(cdvar) ) THEN
357         ! check the variable exists in the file
358         llok = NF90_INQ_VARID( if90id, TRIM(cdvar), ivarid ) == nf90_noerr
359         IF( llok ) &
360            ! check the variable has the attribute required
361            llok = NF90_Inquire_attribute(if90id, ivarid, cdatt, len=isize ) == nf90_noerr
362      ELSE
363         llok = NF90_Inquire_attribute(if90id, NF90_GLOBAL, cdatt, len=isize ) == nf90_noerr
364      ENDIF
365      !
366      IF( PRESENT(ksize) ) ksize = isize
367      !
368      IF( .not. llok) &
369         CALL ctl_warn('iom_nf90_chkatt: no attribute '//cdatt//' found')
370      !
371   END SUBROUTINE iom_nf90_chkatt
372
373
374   !!----------------------------------------------------------------------
375   !!                   INTERFACE iom_nf90_getatt
376   !!----------------------------------------------------------------------
377
378   SUBROUTINE iom_nf90_getatt( kiomid, cdatt, katt0d, katt1d, patt0d, patt1d, cdatt0d, cdvar)
379      !!-----------------------------------------------------------------------
380      !!                  ***  ROUTINE  iom_nf90_getatt  ***
381      !!
382      !! ** Purpose : read an attribute with NF90
383      !!              (either a global attribute (default) or a variable
384      !!               attribute if optional variable name is supplied (cdvar))
385      !!-----------------------------------------------------------------------
386      INTEGER               , INTENT(in   )           ::   kiomid   ! Identifier of the file
387      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt    ! attribute name
388      INTEGER               , INTENT(  out), OPTIONAL ::   katt0d   ! read scalar integer
389      INTEGER, DIMENSION(:) , INTENT(  out), OPTIONAL ::   katt1d   ! read 1d array integer
390      REAL(wp)              , INTENT(  out), OPTIONAL ::   patt0d   ! read scalar  real
391      REAL(wp), DIMENSION(:), INTENT(  out), OPTIONAL ::   patt1d   ! read 1d array real
392      CHARACTER(len=*)      , INTENT(  out), OPTIONAL ::   cdatt0d  ! read character
393      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar    ! name of the variable
394      !
395      INTEGER                         ::   if90id   ! temporary integer
396      INTEGER                         ::   ivarid   ! NetCDF variable Id
397      LOGICAL                         ::   llok     ! temporary logical
398      CHARACTER(LEN=100)              ::   clinfo   ! info character
399      !---------------------------------------------------------------------
400      !
401      if90id = iom_file(kiomid)%nfid
402      IF( PRESENT(cdvar) ) THEN
403         ! check the variable exists in the file
404         llok = NF90_INQ_VARID( if90id, TRIM(cdvar), ivarid ) == nf90_noerr
405         IF( llok ) THEN
406            ! check the variable has the attribute required
407            llok = NF90_Inquire_attribute(if90id, ivarid, cdatt) == nf90_noerr
408         ELSE
409            CALL ctl_warn('iom_nf90_getatt: no variable '//TRIM(cdvar)//' found')
410         ENDIF
411      ELSE
412         llok = NF90_Inquire_attribute(if90id, NF90_GLOBAL, cdatt) == nf90_noerr
413         ivarid = NF90_GLOBAL
414      ENDIF
415      !
416      IF( llok) THEN
417         clinfo = 'iom_nf90_getatt, file: '//TRIM(iom_file(kiomid)%name)//', att: '//TRIM(cdatt)
418         IF(PRESENT( katt0d))   CALL iom_nf90_check(NF90_GET_ATT(if90id, ivarid, cdatt, values =  katt0d), clinfo)
419         IF(PRESENT( katt1d))   CALL iom_nf90_check(NF90_GET_ATT(if90id, ivarid, cdatt, values =  katt1d), clinfo)
420         IF(PRESENT( patt0d))   CALL iom_nf90_check(NF90_GET_ATT(if90id, ivarid, cdatt, values =  patt0d), clinfo)
421         IF(PRESENT( patt1d))   CALL iom_nf90_check(NF90_GET_ATT(if90id, ivarid, cdatt, values =  patt1d), clinfo)
422         IF(PRESENT(cdatt0d))   CALL iom_nf90_check(NF90_GET_ATT(if90id, ivarid, cdatt, values = cdatt0d), clinfo)
423      ELSE
424         CALL ctl_warn('iom_nf90_getatt: no attribute '//TRIM(cdatt)//' found')
425         IF(PRESENT( katt0d))    katt0d    = -999
426         IF(PRESENT( katt1d))    katt1d(:) = -999
427         IF(PRESENT( patt0d))    patt0d    = -999._wp
428         IF(PRESENT( patt1d))    patt1d(:) = -999._wp
429         IF(PRESENT(cdatt0d))   cdatt0d    = '!'
430      ENDIF
431      !
432   END SUBROUTINE iom_nf90_getatt
433
434
435   SUBROUTINE iom_nf90_putatt( kiomid, cdatt, katt0d, katt1d, patt0d, patt1d, cdatt0d, cdvar)
436      !!-----------------------------------------------------------------------
437      !!                  ***  ROUTINE  iom_nf90_putatt  ***
438      !!
439      !! ** Purpose : write an attribute with NF90
440      !!              (either a global attribute (default) or a variable
441      !!               attribute if optional variable name is supplied (cdvar))
442      !!-----------------------------------------------------------------------
443      INTEGER               , INTENT(in   )           ::   kiomid   ! Identifier of the file
444      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt    ! attribute name
445      INTEGER               , INTENT(in   ), OPTIONAL ::   katt0d   ! read scalar integer
446      INTEGER, DIMENSION(:) , INTENT(in   ), OPTIONAL ::   katt1d   ! read 1d array integer
447      REAL(wp)              , INTENT(in   ), OPTIONAL ::   patt0d   ! read scalar  real
448      REAL(wp), DIMENSION(:), INTENT(in   ), OPTIONAL ::   patt1d   ! read 1d array real
449      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdatt0d  ! read character
450      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar    ! name of the variable
451      !
452      INTEGER                         ::   if90id   ! temporary integer
453      INTEGER                         ::   ivarid   ! NetCDF variable Id
454      INTEGER                         ::   isize    ! Attribute size
455      INTEGER                         ::   itype    ! Attribute type
456      LOGICAL                         ::   llok     ! temporary logical
457      LOGICAL                         ::   llatt     ! temporary logical
458      LOGICAL                         ::   lldata   ! temporary logical
459      CHARACTER(LEN=100)              ::   clinfo   ! info character
460      !---------------------------------------------------------------------
461      !
462      if90id = iom_file(kiomid)%nfid
463      IF( PRESENT(cdvar) ) THEN
464         llok = NF90_INQ_VARID( if90id, TRIM(cdvar), ivarid ) == nf90_noerr   ! is the variable in the file?
465         IF( .NOT. llok ) THEN
466            CALL ctl_warn('iom_nf90_putatt: no variable '//TRIM(cdvar)//' found'   &
467               &        , '                 no attribute '//cdatt//' written' )
468            RETURN
469         ENDIF
470      ELSE
471         ivarid = NF90_GLOBAL
472      ENDIF
473      llatt = NF90_Inquire_attribute(if90id, ivarid, cdatt, len = isize, xtype = itype ) == nf90_noerr
474      !
475      ! trick: irec used to know if the file is in define mode or not
476      lldata = iom_file(kiomid)%irec /= -1   ! default: go back in define mode if in data mode
477      IF( lldata .AND. llatt ) THEN          ! attribute already there. Do we really need to go back in define mode?
478         ! do we have the appropriate type?
479         IF(PRESENT( katt0d) .OR. PRESENT( katt1d))   llok = itype == NF90_INT
480         IF(PRESENT( patt0d) .OR. PRESENT( patt1d))   llok = itype == NF90_DOUBLE
481         IF(PRESENT(cdatt0d)                      )   llok = itype == NF90_CHAR
482         ! and do we have the appropriate size?
483         IF(PRESENT( katt0d))   llok = llok .AND. isize == 1
484         IF(PRESENT( katt1d))   llok = llok .AND. isize == SIZE(katt1d)
485         IF(PRESENT( patt0d))   llok = llok .AND. isize == 1
486         IF(PRESENT( patt1d))   llok = llok .AND. isize == SIZE(patt1d)
487         IF(PRESENT(cdatt0d))   llok = llok .AND. isize == LEN_TRIM(cdatt0d)
488         !
489         lldata = .NOT. llok
490      ENDIF
491      !
492      clinfo = 'iom_nf90_putatt, file: '//TRIM(iom_file(kiomid)%name)//', att: '//TRIM(cdatt)
493      IF(lldata)   CALL iom_nf90_check(NF90_REDEF( if90id ), clinfo)   ! leave data mode to define mode
494      !
495      IF(PRESENT( katt0d))   CALL iom_nf90_check(NF90_PUT_ATT(if90id, ivarid, cdatt, values =       katt0d) , clinfo)
496      IF(PRESENT( katt1d))   CALL iom_nf90_check(NF90_PUT_ATT(if90id, ivarid, cdatt, values =       katt1d) , clinfo)
497      IF(PRESENT( patt0d))   CALL iom_nf90_check(NF90_PUT_ATT(if90id, ivarid, cdatt, values =       patt0d) , clinfo)
498      IF(PRESENT( patt1d))   CALL iom_nf90_check(NF90_PUT_ATT(if90id, ivarid, cdatt, values =       patt1d) , clinfo)
499      IF(PRESENT(cdatt0d))   CALL iom_nf90_check(NF90_PUT_ATT(if90id, ivarid, cdatt, values = trim(cdatt0d)), clinfo)
500      !
501      IF(lldata)   CALL iom_nf90_check(NF90_ENDDEF( if90id ), clinfo)   ! leave define mode to data mode
502      !
503   END SUBROUTINE iom_nf90_putatt
504
505
506   SUBROUTINE iom_nf90_rp0123d( kt, kwrite, kiomid, cdvar , kvid  , ktype,   &
507         &                                  pv_r0d, pv_r1d, pv_r2d, pv_r3d )
508      !!--------------------------------------------------------------------
509      !!                   ***  SUBROUTINE  iom_nf90_rstput  ***
510      !!
511      !! ** Purpose : read the time axis cdvar in the file
512      !!--------------------------------------------------------------------
513      INTEGER                     , INTENT(in)           ::   kt       ! ocean time-step
514      INTEGER                     , INTENT(in)           ::   kwrite   ! writing time-step
515      INTEGER                     , INTENT(in)           ::   kiomid   ! Identifier of the file
516      CHARACTER(len=*)            , INTENT(in)           ::   cdvar    ! variable name
517      INTEGER                     , INTENT(in)           ::   kvid     ! variable id
518      INTEGER                     , INTENT(in), OPTIONAL ::   ktype    ! variable type (default R8)
519      REAL(wp)                    , INTENT(in), OPTIONAL ::   pv_r0d   ! written Od field
520      REAL(wp), DIMENSION(      :), INTENT(in), OPTIONAL ::   pv_r1d   ! written 1d field
521      REAL(wp), DIMENSION(:, :   ), INTENT(in), OPTIONAL ::   pv_r2d   ! written 2d field
522      REAL(wp), DIMENSION(:, :, :), INTENT(in), OPTIONAL ::   pv_r3d   ! written 3d field
523      !
524      INTEGER               :: idims                ! number of dimension
525      INTEGER               :: idvar                ! variable id
526      INTEGER               :: jd                   ! dimension loop counter   
527      INTEGER               :: ix1, ix2, iy1, iy2   ! subdomain indexes   
528      INTEGER, DIMENSION(4) :: idimsz               ! dimensions size 
529      INTEGER, DIMENSION(4) :: idimid               ! dimensions id
530      CHARACTER(LEN=256)    :: clinfo               ! info character
531      CHARACTER(LEN= 12), DIMENSION(5) :: cltmp     ! temporary character
532      INTEGER               :: if90id               ! nf90 file identifier
533      INTEGER               :: idmy                 ! dummy variable
534      INTEGER               :: itype                ! variable type
535      INTEGER, DIMENSION(4) :: ichunksz             ! NetCDF4 chunk sizes. Will be computed using
536      !                                             ! nn_nchunks_[i,j,k,t] namelist parameters
537      INTEGER               :: ichunkalg, ishuffle, ideflate, ideflate_level
538      !                                             ! NetCDF4 internally fixed parameters
539      LOGICAL               :: lchunk               ! logical switch to activate chunking and compression
540      !                                             ! when appropriate (currently chunking is applied to 4d fields only)
541      INTEGER               :: idlv                 ! local variable
542      INTEGER               :: idim3                ! id of the third dimension
543      !---------------------------------------------------------------------
544      !
545      clinfo = '          iom_nf90_rp0123d, file: '//TRIM(iom_file(kiomid)%name)//', var: '//TRIM(cdvar)
546      if90id = iom_file(kiomid)%nfid
547      !
548      ! define dimension variables if it is not already done
549      ! ==========================
550      IF( iom_file(kiomid)%nvars == 0 ) THEN
551         ! are we in define mode?
552         IF( iom_file(kiomid)%irec /= -1 ) THEN   ! trick: irec used to know if the file is in define mode or not
553            CALL iom_nf90_check(NF90_REDEF( if90id ), clinfo)   ;   iom_file(kiomid)%irec = -1
554         ENDIF
555         ! define the dimension variables if it is not already done
556         ! Warning: we must use the same character length in an array constructor (at least for gcc compiler)
557         cltmp = (/ 'nav_lon     ', 'nav_lat     ', 'nav_lev     ', 'time_counter', 'numcat      ' /)   
558         CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cltmp(1)), NF90_FLOAT , (/ 1, 2 /), iom_file(kiomid)%nvid(1) ), clinfo)
559         CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cltmp(2)), NF90_FLOAT , (/ 1, 2 /), iom_file(kiomid)%nvid(2) ), clinfo)
560         CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cltmp(3)), NF90_FLOAT , (/ 3    /), iom_file(kiomid)%nvid(3) ), clinfo)
561         CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cltmp(4)), NF90_DOUBLE, (/ 4    /), iom_file(kiomid)%nvid(4) ), clinfo)
562         ! update informations structure related the dimension variable we just added...
563         iom_file(kiomid)%nvars       = 4
564         iom_file(kiomid)%luld(1:4)   = (/ .FALSE., .FALSE., .FALSE., .TRUE. /)
565         iom_file(kiomid)%cn_var(1:4) = cltmp(1:4)
566         iom_file(kiomid)%ndims(1:4)  = (/ 2, 2, 1, 1 /)
567         IF( NF90_INQ_DIMID( if90id, 'numcat', idmy ) == nf90_noerr ) THEN   ! add a 5th variable corresponding to the 5th dimension
568            CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cltmp(5)), NF90_FLOAT , (/ 5 /), iom_file(kiomid)%nvid(5) ), clinfo)
569            iom_file(kiomid)%nvars     = 5
570            iom_file(kiomid)%luld(5)   = .FALSE.
571            iom_file(kiomid)%cn_var(5) = cltmp(5)
572            iom_file(kiomid)%ndims(5)  = 1
573         ENDIF
574         ! trick: defined to 0 to say that dimension variables are defined but not yet written
575         iom_file(kiomid)%dimsz(1, 1)  = 0   
576         IF(lwp) WRITE(numout,*) TRIM(clinfo)//' define dimension variables done'
577      ENDIF
578      ! define the data if it is not already done
579      ! ===============
580      IF( kvid <= 0 ) THEN
581         !
582         ! NetCDF4 chunking and compression fixed settings
583         ichunkalg = 0
584         ishuffle = 1
585         ideflate = 1
586         ideflate_level = 1
587         !
588         idvar = iom_file(kiomid)%nvars + 1
589         ! are we in define mode?
590         IF( iom_file(kiomid)%irec /= -1 ) THEN   ! trick: irec used to know if the file is in define mode or not
591            CALL iom_nf90_check(NF90_REDEF( if90id ), clinfo)   ;   iom_file(kiomid)%irec = -1
592         ENDIF
593         ! variable definition
594         IF(     PRESENT(pv_r0d) ) THEN   ;   idims = 0
595         ELSEIF( PRESENT(pv_r1d) ) THEN
596            IF(( SIZE(pv_r1d,1) == jpk ).OR.( SIZE(pv_r1d,1) == jpka )) THEN   ;   idim3 = 3
597            ELSE                                                               ;   idim3 = 5
598            ENDIF
599                                              idims = 2   ;   idimid(1:idims) = (/idim3,4/)
600         ELSEIF( PRESENT(pv_r2d) ) THEN   ;   idims = 3   ;   idimid(1:idims) = (/1,2  ,4/)
601         ELSEIF( PRESENT(pv_r3d) ) THEN
602            IF(( SIZE(pv_r3d,3) == jpk ).OR.( SIZE(pv_r3d,3) == jpka )) THEN   ;   idim3 = 3
603            ELSE                                                               ;   idim3 = 5
604            ENDIF
605                                              idims = 4   ;   idimid(1:idims) = (/1,2,idim3,4/)
606         ENDIF
607         IF( PRESENT(ktype) ) THEN   ! variable external type
608            SELECT CASE (ktype)
609            CASE (jp_r8)   ;   itype = NF90_DOUBLE
610            CASE (jp_r4)   ;   itype = NF90_FLOAT
611            CASE (jp_i4)   ;   itype = NF90_INT
612            CASE (jp_i2)   ;   itype = NF90_SHORT
613            CASE (jp_i1)   ;   itype = NF90_BYTE
614            CASE DEFAULT   ;   CALL ctl_stop( TRIM(clinfo)//' unknown variable type' )
615            END SELECT
616         ELSE
617            itype = NF90_DOUBLE
618         ENDIF
619         IF( PRESENT(pv_r0d) ) THEN
620            CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cdvar), itype,                    &
621               &                              iom_file(kiomid)%nvid(idvar) ), clinfo )
622         ELSE
623            CALL iom_nf90_check(NF90_DEF_VAR( if90id, TRIM(cdvar), itype, idimid(1:idims),   &
624               &                              iom_file(kiomid)%nvid(idvar) ), clinfo )
625         ENDIF
626         lchunk = .false.
627         IF( snc4set%luse .AND. idims == 4 )   lchunk = .true.
628         ! update informations structure related the new variable we want to add...
629         iom_file(kiomid)%nvars         = idvar
630         iom_file(kiomid)%cn_var(idvar) = TRIM(cdvar)
631         iom_file(kiomid)%scf(idvar)    = 1.
632         iom_file(kiomid)%ofs(idvar)    = 0.
633         iom_file(kiomid)%ndims(idvar)  = idims
634         IF( .NOT. PRESENT(pv_r0d) ) THEN   ;   iom_file(kiomid)%luld(idvar) = .TRUE.
635         ELSE                               ;   iom_file(kiomid)%luld(idvar) = .FALSE.
636         ENDIF
637         DO jd = 1, idims
638            CALL iom_nf90_check(NF90_INQUIRE_DIMENSION( if90id, idimid(jd), len = iom_file(kiomid)%dimsz(jd,idvar) ), clinfo)
639            IF ( lchunk ) ichunksz(jd) = iom_file(kiomid)%dimsz(jd,idvar)
640         END DO
641         IF ( lchunk ) THEN
642            ! Calculate chunk sizes by partitioning each dimension as requested in namnc4 namelist
643            ! Disallow very small chunk sizes and prevent chunk sizes larger than each individual dimension
644            ichunksz(1) = MIN( ichunksz(1),MAX( (ichunksz(1)-1)/snc4set%ni + 1 ,16 ) ) ! Suggested default nc4set%ni=4
645            ichunksz(2) = MIN( ichunksz(2),MAX( (ichunksz(2)-1)/snc4set%nj + 1 ,16 ) ) ! Suggested default nc4set%nj=2
646            ichunksz(3) = MIN( ichunksz(3),MAX( (ichunksz(3)-1)/snc4set%nk + 1 , 1 ) ) ! Suggested default nc4set%nk=6
647            ichunksz(4) = 1                                                            ! Do not allow chunks to span the
648            !                                                                          ! unlimited dimension
649            CALL iom_nf90_check(SET_NF90_DEF_VAR_CHUNKING(if90id, idvar, ichunkalg, ichunksz), clinfo)
650            CALL iom_nf90_check(SET_NF90_DEF_VAR_DEFLATE(if90id, idvar, ishuffle, ideflate, ideflate_level), clinfo)
651            IF(lwp) WRITE(numout,*) TRIM(clinfo)//' chunked ok. Chunks sizes: ', ichunksz
652         ENDIF
653         IF(lwp) WRITE(numout,*) TRIM(clinfo)//' defined ok'
654      ELSE
655         idvar = kvid
656      ENDIF
657      !
658      ! time step kwrite : write the variable
659      IF( kt == kwrite ) THEN
660         ! are we in write mode?
661         IF( iom_file(kiomid)%irec == -1 ) THEN   ! trick: irec used to know if the file is in define mode or not
662            CALL iom_nf90_check(NF90_ENDDEF( if90id ), clinfo)   ;   iom_file(kiomid)%irec = 0
663         ENDIF
664         ! on what kind of domain must the data be written?
665         IF( PRESENT(pv_r2d) .OR. PRESENT(pv_r3d) ) THEN
666            idimsz(1:2) = iom_file(kiomid)%dimsz(1:2,idvar)
667            IF(     idimsz(1) == (nlei - nldi + 1) .AND. idimsz(2) == (nlej - nldj + 1) ) THEN
668               ix1 = nldi   ;   ix2 = nlei   ;   iy1 = nldj   ;   iy2 = nlej
669            ELSEIF( idimsz(1) == nlci              .AND. idimsz(2) == nlcj              ) THEN
670               ix1 = 1      ;   ix2 = nlci   ;   iy1 = 1      ;   iy2 = nlcj
671            ELSEIF( idimsz(1) == jpi               .AND. idimsz(2) == jpj               ) THEN
672               ix1 = 1      ;   ix2 = jpi    ;   iy1 = 1      ;   iy2 = jpj
673            ELSE
674               CALL ctl_stop( 'iom_nf90_rp0123d: should have been an impossible case...' )
675            ENDIF
676
677            ! write dimension variables if it is not already done
678            ! =============
679            ! trick: is defined to 0 => dimension variable are defined but not yet written
680            IF( iom_file(kiomid)%dimsz(1, 1) == 0 ) THEN
681               CALL iom_nf90_check( NF90_INQ_VARID( if90id, 'nav_lon'     , idmy )         , clinfo )
682               CALL iom_nf90_check( NF90_PUT_VAR  ( if90id, idmy, glamt(ix1:ix2, iy1:iy2) ), clinfo )
683               CALL iom_nf90_check( NF90_INQ_VARID( if90id, 'nav_lat'     , idmy )         , clinfo )
684               CALL iom_nf90_check( NF90_PUT_VAR  ( if90id, idmy, gphit(ix1:ix2, iy1:iy2) ), clinfo )
685               CALL iom_nf90_check( NF90_INQ_VARID( if90id, 'nav_lev'     , idmy ), clinfo )
686               IF (iom_file(kiomid)%nlev == jpka) THEN   ;   CALL iom_nf90_check( NF90_PUT_VAR  ( if90id, idmy,  ght_abl), clinfo )
687               ELSE                                      ;   CALL iom_nf90_check( NF90_PUT_VAR  ( if90id, idmy, gdept_1d), clinfo )
688               ENDIF
689               IF( NF90_INQ_VARID( if90id, 'numcat', idmy ) == nf90_noerr ) THEN
690                  CALL iom_nf90_check( NF90_PUT_VAR  ( if90id, idmy, (/ (idlv, idlv = 1,iom_file(kiomid)%nlev) /)), clinfo )
691               ENDIF
692               ! +++ WRONG VALUE: to be improved but not really useful...
693               CALL iom_nf90_check( NF90_INQ_VARID( if90id, 'time_counter', idmy ), clinfo )
694               CALL iom_nf90_check( NF90_PUT_VAR( if90id, idmy, kt                      ), clinfo )   
695               ! update the values of the variables dimensions size
696               CALL iom_nf90_check( NF90_INQUIRE_DIMENSION( if90id, 1, len = iom_file(kiomid)%dimsz(1,1) ), clinfo )
697               CALL iom_nf90_check( NF90_INQUIRE_DIMENSION( if90id, 2, len = iom_file(kiomid)%dimsz(2,1) ), clinfo )
698               iom_file(kiomid)%dimsz(1:2, 2) = iom_file(kiomid)%dimsz(1:2, 1)
699               CALL iom_nf90_check( NF90_INQUIRE_DIMENSION( if90id, 3, len = iom_file(kiomid)%dimsz(1,3) ), clinfo )
700               iom_file(kiomid)%dimsz(1  , 4) = 1   ! unlimited dimension
701               IF(lwp) WRITE(numout,*) TRIM(clinfo)//' write dimension variables done'
702            ENDIF
703         ENDIF
704
705         ! write the data
706         ! =============
707         IF(     PRESENT(pv_r0d) ) THEN
708            CALL iom_nf90_check( NF90_PUT_VAR( if90id, idvar, pv_r0d                    ), clinfo )
709         ELSEIF( PRESENT(pv_r1d) ) THEN
710            CALL iom_nf90_check( NF90_PUT_VAR( if90id, idvar, pv_r1d(:)                 ), clinfo )
711         ELSEIF( PRESENT(pv_r2d) ) THEN
712            CALL iom_nf90_check( NF90_PUT_VAR( if90id, idvar, pv_r2d(ix1:ix2,iy1:iy2)   ), clinfo )
713         ELSEIF( PRESENT(pv_r3d) ) THEN
714            CALL iom_nf90_check( NF90_PUT_VAR( if90id, idvar, pv_r3d(ix1:ix2,iy1:iy2,:) ), clinfo )
715         ENDIF
716         ! add 1 to the size of the temporal dimension (not really useful...)
717         IF( iom_file(kiomid)%luld(idvar) )   iom_file(kiomid)%dimsz(iom_file(kiomid)%ndims(idvar), idvar)    &
718               &                            = iom_file(kiomid)%dimsz(iom_file(kiomid)%ndims(idvar), idvar) + 1
719         IF(lwp) WRITE(numout,*) TRIM(clinfo)//' written ok'
720      ENDIF
721      !     
722   END SUBROUTINE iom_nf90_rp0123d
723
724
725   SUBROUTINE iom_nf90_check( kstatus, cdinfo )
726      !!--------------------------------------------------------------------
727      !!                   ***  SUBROUTINE iom_nf90_check  ***
728      !!
729      !! ** Purpose :   check nf90 errors
730      !!--------------------------------------------------------------------
731      INTEGER,          INTENT(in) :: kstatus
732      CHARACTER(LEN=*), INTENT(in) :: cdinfo
733      !---------------------------------------------------------------------
734      IF(kstatus /= nf90_noerr)   CALL ctl_stop( 'iom_nf90_check : '//TRIM(nf90_strerror(kstatus)), TRIM(cdinfo) )
735   END SUBROUTINE iom_nf90_check
736
737   !!======================================================================
738END MODULE iom_nf90
Note: See TracBrowser for help on using the repository browser.