Subversion Repositories lagranto.ecmwf

Rev

Rev 46 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
46 michaesp 1
c     ************************************************************
2
c     * This package provides input routines to read the wind    *
3
c     * and other fields from IVE necdf files. The routines are  *
4
c     *                                                          *
5
c     * 1) input_open  : to open a data file                     *
6
c     * 2) input_grid  : to read the grid information, including *
7
c     *                  the vertical levels                     *
8
c     * 3) input_wind  : to read the wind components             *
9
c     * 4) input_close : to close an input file                  *
10
c     *                                                          *
11
c     * The file is characterised by an filename <filename> and  *
12
c     * a file identifier <fid>. The horizontal grid is given by *
13
c     * <xmin,xmax,ymin,ymax,dx,dy,nx,ny> where the pole of the  *
14
c     * rotated grid is given by <pollon,pollat>. The vertical   *
15
c     * grid is characterised by the surface pressure <ps> and   *
16
c     * the pressure at staggered <slev> and unstaggered <ulev>  *
17
c     * levels. The number of levels is given by <nz>. Finally,  *
18
c     * the retrieval of the wind <field> with name <fieldname>  *
19
c     * is characterised by a <time> and a missing data value    *
20
c     * <mdv>.                                                   *
21
c     *                                                          *
22
c     * Author: Michael Sprenger, Autumn 2008                    *
23
c     ************************************************************
24
 
25
c     ------------------------------------------------------------
26
c     Open input file
27
c     ------------------------------------------------------------
28
 
29
      subroutine input_open (fid,filename)
30
 
31
c     Open the input file with filename <filename> and return the
32
c     file identifier <fid> for further reference. 
33
 
34
      use netcdf
35
 
36
      implicit none
37
 
38
c     Declaration of subroutine parameters
39
      integer      fid              ! File identifier
40
      character*80 filename         ! Filename
41
 
42
c     Declaration of auxiliary variables
43
      integer      ierr
44
 
45
c     Open netcdf file
46
      ierr = NF90_OPEN(TRIM(filename),nf90_nowrite, fid)
47
      IF ( ierr /= nf90_NoErr ) PRINT *,NF90_STRERROR(ierr)
48
 
49
c     Exception handling
50
      return
51
 
52
      end
53
 
54
c     ------------------------------------------------------------
55
c     Read information about the grid
56
c     ------------------------------------------------------------
57
 
58
      subroutine input_grid 
59
     >                   (fid,fieldname,xmin,xmax,ymin,ymax,dx,dy,nx,ny,
60
     >                    time,pollon,pollat,p3,ps,nz,ak,bk,stagz,
61
     >                    timecheck)
62
 
63
c     Read grid information at <time> from file with identifier <fid>. 
64
c     The horizontal grid is characterized by <xmin,xmax,ymin,ymax,dx,dy>
65
c     with pole position at <pollon,pollat> and grid dimension <nx,ny>.
66
c     The 3d arrays <p3(nx,ny,nz)> gives the vertical coordinates, either
67
c     on the staggered or unstaggered grid (with <stagz> as the flag).
68
c     The surface pressure is given in <ps(nx,ny)>. If <fid> is negative, 
69
c     only the grid dimensions and grid parameters (xmin...pollat,nz) are 
70
c     determined and returned (this is needed for dynamical allocation of 
71
c     memory).
72
 
73
      use netcdf
74
 
75
      implicit none
76
 
77
c     Declaration of subroutine parameters 
78
      integer      fid                 ! File identifier
79
      real         xmin,xmax,ymin,ymax ! Domain size
80
      real         dx,dy               ! Horizontal resolution
81
      integer      nx,ny,nz            ! Grid dimensions
82
      real         pollon,pollat       ! Longitude and latitude of pole
83
      real         p3(nx,ny,nz)        ! Staggered levels
84
      real         ps(nx,ny)           ! Surface pressure
85
      real         time                ! Time of the grid information
86
      real         ak(nz),bk(nz)       ! Ak and Bk for layers or levels
87
      real         stagz               ! Vertical staggering (0 or -0.5)
88
      character*80 fieldname           ! Variable from which to take grid info
89
      character*80 timecheck           ! Either 'yes' or 'no'
90
 
91
c     Numerical and physical parameters
92
      real          eps                 ! Numerical epsilon
93
      parameter    (eps=0.001)
94
 
95
c     Netcdf variables
96
      integer      vardim(4)
97
      real         varmin(4),varmax(4)
98
      real         mdv
99
      real         stag(4)
100
      integer      ndim
101
      character*80 cstfile
102
      integer      cstid
103
      integer      nvars
104
      character*80 vars(100)
105
      integer        dimids (nf90_max_var_dims),dimid
106
      character*80   dimname(nf90_max_var_dims)
107
      character*80   stdname
108
      real,allocatable, dimension (:)     :: lon,lat,lev
109
      real,allocatable, dimension (:)     :: times
110
      real,allocatable, dimension (:,:)   :: tmp2
111
      real,allocatable, dimension (:,:,:) :: tmp3
112
      real,allocatable, dimension (:)     :: aktmp,bktmp
113
      character*80  units
114
      character*80  leveltype
115
      integer       nakbktmp
116
      integer       vertical_swap
117
 
118
c     Auxiliary variables
119
      integer      ierr       
120
      integer      i,j,k
121
      integer      isok
122
      real         tmp(200)
123
      character*80 varname
124
      real         rtime
125
      integer      varid
126
      integer      cdfid
127
      integer      stat
128
      real         delta
129
      integer      closear
130
      real         maxps,minps
131
 
132
c     ---- Read data from netCDF file as they are ---------------------
133
 
134
c     Set file identifier
135
      if (fid.lt.0) then
136
        cdfid = -fid
137
      else 
138
        cdfid = fid
139
      endif
140
 
141
c     Special handling if 3D pressure is
142
      if ( fieldname.eq.'P' ) then
143
         fieldname = 'U'
144
      endif
145
 
146
c     Get number of dimensions of variable -> ndim
147
      ierr = NF90_INQ_VARID(cdfid,fieldname,varid)
148
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
149
      ierr = nf90_inquire_variable(cdfid, varid, ndims  = ndim)
150
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
151
c      if ( ndim.ne.4 ) then
152
c          print*,' ERROR: netCDF variables need to be 4D'
153
c          print*,'      ',trim(fieldname)
154
c          stop
155
c      endif
156
 
157
c     Get dimensions -> vardim(1:ndim),dimname(1:ndim)
158
      ierr = NF90_INQ_VARID(cdfid,fieldname,varid)
159
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
160
      ierr = nf90_inquire_variable(cdfid, varid, 
161
     >                                   dimids = dimids(1:ndim))
162
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
163
      do i=1,ndim
164
           ierr = nf90_inquire_dimension(cdfid, dimids(i), 
165
     >                               name = dimname(i) )
166
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
167
           ierr = nf90_inquire_dimension(cdfid, dimids(i),len=vardim(i))
168
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
169
      enddo
170
 
171
c     Check whether the list of dimensions is OK
172
      if ( ndim.eq.4 ) then
173
        if ( ( dimname(1).ne.'lon'  ).or.
174
     >     ( dimname(2).ne.'lat'  ).or. 
175
     >     ( dimname(3).ne.'lev'  ).and.( dimname(3).ne.'lev_2'  ).or.
176
     >     ( dimname(4).ne.'time' ) )
177
     >  then
178
         print*,' ERROR: the dimensions of the variable are not correct'
179
         print*,'        expected -> lon / lat / lev / time'
180
         print*, ( trim(dimname(i))//' / ',i=1,ndim )
181
         stop
182
        endif
183
      else
184
        if ( ( dimname(1).ne.'lon'  ).or.
185
     >       ( dimname(2).ne.'lat'  ).or.
186
     >       ( dimname(3).ne.'time' ) )
187
     >  then
188
         print*,' ERROR: the dimensions of the variable are not correct'
189
         print*,'        expected -> lon / lat / time'
190
         print*, ( trim(dimname(i))//' / ',i=1,ndim )
191
         stop
192
        endif
193
      endif
47 michaesp 194
 
46 michaesp 195
c     Check about the type of vertical levels
196
      if ( ndim.eq.4 ) then
197
 
198
c         Get dimension of AK,BK
199
          varname = 'nhym'
200
          ierr = NF90_INQ_DIMID(cdfid,varname,dimid)
201
          ierr = nf90_inquire_dimension(cdfid, dimid,len=nakbktmp)
202
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
203
 
204
          varname=dimname(3)
205
          ierr = NF90_INQ_VARID(cdfid,varname,varid)
206
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
207
          ierr = nf90_get_att(cdfid, varid, "standard_name", leveltype)
208
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
209
          if ( (leveltype.ne.'hybrid_sigma_pressure').and.
210
     >         (leveltype.ne.'air_pressure'         ) )
211
     >    then
212
             print*,' ERROR: input netCDF data must be on hybrid-sigma'
213
             print*,'        or air pressure levels!',trim(leveltype)
214
             stop
215
          endif
216
      else
217
          leveltype='air_pressure'
218
      endif
219
 
220
c     Allocate memory for reading arrays
221
      allocate(tmp2(vardim(1),vardim(2)),stat=stat)
222
      if (stat.ne.0) print*,'*** error allocating array tmp2     ***'
223
      allocate(tmp3(vardim(1),vardim(2),vardim(3)),stat=stat)
224
      if (stat.ne.0) print*,'*** error allocating array tmp3     ***'
225
      allocate(lon(vardim(1)),stat=stat)
226
      if (stat.ne.0) print*,'*** error allocating array lon     ***' 
227
      allocate(lat(vardim(2)),stat=stat)
228
      if (stat.ne.0) print*,'*** error allocating array lat     ***' 
229
      if ( ndim.eq.4 ) then
230
        allocate(aktmp(nakbktmp),stat=stat)
231
        if (stat.ne.0) print*,'*** error allocating array aktmp   ***'
232
        allocate(bktmp(nakbktmp),stat=stat)
233
        if (stat.ne.0) print*,'*** error allocating array bktmp   ***'
47 michaesp 234
        allocate(lev(vardim(3)),stat=stat)
235
        if (stat.ne.0) print*,'*** error allocating array lev     ***'
236
        allocate(times(vardim(4)),stat=stat)
237
        if (stat.ne.0) print*,'*** error allocating array times   ***'
238
      elseif ( ndim.eq.3 ) then
239
        allocate(aktmp(nakbktmp),stat=stat)
240
        if (stat.ne.0) print*,'*** error allocating array aktmp   ***'
241
        allocate(bktmp(nakbktmp),stat=stat)
242
        if (stat.ne.0) print*,'*** error allocating array bktmp   ***'
243
        allocate(lev(vardim(3)),stat=stat)
244
        allocate(times(vardim(3)),stat=stat)
245
        if (stat.ne.0) print*,'*** error allocating array times   ***'
46 michaesp 246
      endif
247
 
248
c     Get domain longitudes, latitudes and levels
249
      varname = dimname(1)
250
      ierr = NF90_INQ_VARID(cdfid,varname,varid)
251
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
252
      ierr = nf90_get_var(cdfid,varid,lon)
253
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
254
      varname = dimname(2)
255
      ierr = NF90_INQ_VARID(cdfid,varname,varid)
256
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
257
      ierr = nf90_get_var(cdfid,varid,lat)
258
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
259
      varname = dimname(3)
260
      ierr = NF90_INQ_VARID(cdfid,varname,varid)
261
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
262
      ierr = nf90_get_var(cdfid,varid,lev)
263
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
264
 
265
c     Get ak and bk
266
      if ( ndim.eq.4 ) then
267
 
268
c       Read ak, bk
269
        varname='hyam'
270
        ierr = NF90_INQ_VARID(cdfid,varname,varid)
271
        IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
272
        ierr = nf90_get_var(cdfid,varid,aktmp)
273
        IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
274
        varname='hybm'
275
        ierr = NF90_INQ_VARID(cdfid,varname,varid)
276
        IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
277
        ierr = nf90_get_var(cdfid,varid,bktmp)
278
        IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
279
 
280
c       Check that unit of ak is in hPa - if necessary correct it
281
        varname='hyam'
282
        ierr = NF90_INQ_VARID(cdfid,varname,varid)
283
        IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
284
        ierr = nf90_get_att(cdfid, varid, "units", units)
285
        IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
286
        if ( units.eq.'Pa' ) then
287
           do k=1,nakbktmp
288
              aktmp(k) = 0.01 * aktmp(k)
289
           enddo
290
        endif
291
      endif
292
 
293
c     Check that unit of lev is in hPa - if necessary correct it
294
      if ( leveltype.eq.'air_pressure' .and. vardim(3) .gt. 1) then
295
         varname='lev'
296
         ierr = NF90_INQ_VARID(cdfid,varname,varid)
297
         IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
298
         ierr = nf90_get_att(cdfid, varid, "units", units)
299
         IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
300
         if ( units.eq.'Pa' ) then
301
            do k=1,vardim(3)
302
               lev(k) = 0.01 * lev(k)
303
            enddo
304
         endif
305
      endif
306
 
307
c     Decide whether to swap vertical levels - highest pressure at index 1
308
      vertical_swap = 1
309
      if ( leveltype.eq.'hybrid_sigma_pressure') then
310
        if ( (aktmp(1) + bktmp(1) * 1000.).gt.
311
     >       (aktmp(2) + bktmp(2) * 1000.) )
312
     >  then
313
          vertical_swap = 0
314
        endif
315
      elseif ( leveltype.eq.'air_pressure') then
316
        if ( lev(1).gt.lev(2) ) then
317
          vertical_swap = 0
318
        endif
319
      endif
320
c      print*,' Vertical SWAP P -> ', vertical_swap
321
 
322
c     Get time information (check if time is correct)
323
      varname = 'time'
324
      ierr = NF90_INQ_VARID(cdfid,varname,varid)
325
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
326
      ierr = nf90_get_var(cdfid,varid,times)
327
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
328
      isok=0
329
      do i=1,vardim(4)
330
        if (abs(time-times(i)).lt.eps) then
331
               isok = 1
332
               rtime = times(i)
333
        elseif (timecheck.eq.'no') then
334
               isok = 1
335
               rtime = times(1)
336
        endif
337
      enddo
338
      if ( isok.eq.0 ) then
339
         print*,' ERROR: time ',rtime,' not found on netCDF file' 
340
         stop
341
      endif
342
 
343
c     Read surface pressure
344
      varname='PS'
345
      ierr = NF90_INQ_VARID(cdfid,varname,varid)
346
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
347
      ierr = nf90_get_var(cdfid,varid,tmp2)
348
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
349
 
350
c     Check that surface pressure is in hPa
351
      if ( leveltype.eq.'hybrid_sigma_pressure' ) then 
352
        maxps = -1.e19
353
        minps =  1.e19
354
        do i=1,vardim(1)
355
          do j=1,vardim(2)
356
             if (tmp2(i,j).gt.maxps) maxps = tmp2(i,j)
357
             if (tmp2(i,j).lt.minps) minps = tmp2(i,j)
358
          enddo
359
        enddo
360
        if ( (maxps.gt.1500.).or.(minps.lt.300.) ) then
361
           print*,' ERROR: surface pressre PS must be in hPa'
362
           print*,'       ',maxps,minps
363
           stop
364
        endif
365
      endif
366
 
367
c     ---- Define output of subroutine --------------------------------
368
 
369
c     If not full list of vertical levels, reduce AK,BK arrays
370
      if ( (leveltype.eq.'hybrid_sigma_pressure').and.
371
     >     (nakbktmp.ne.vardim(3) ) )
372
     >then
373
c         print*,' WARNING: only subset of vertical levels used...'
374
         do k=1,vardim(3)
375
            if ( vertical_swap.eq.1 ) then
376
               aktmp(k) = aktmp( k+nakbktmp-vardim(3) )
377
               bktmp(k) = bktmp( k+nakbktmp-vardim(3) )
378
            endif
379
         enddo
380
      endif
381
 
382
c     Set the grid dimensions and constants
383
      nx      = vardim(1)
384
      ny      = vardim(2)
385
      nz      = vardim(3)
386
      xmin    = lon(1)
387
      ymin    = lat(1)
388
      xmax    = lon(nx)
389
      ymax    = lat(ny)
390
      dx      = (xmax-xmin)/real(nx-1)
391
      dy      = (ymax-ymin)/real(ny-1)
392
      pollon  = 0.
393
      pollat  = 90.
394
      stagz   = 0.
395
      delta   = xmax-xmin-360.
396
      if (abs(delta+dx).lt.eps) then
397
          xmax    = xmax + dx
398
          nx      = nx + 1
399
          closear = 1
400
      else
401
          closear = 0
402
      endif
403
 
404
c     Save the output arrays (if fid>0) - close arrays on request
405
      if ( fid.gt.0 ) then
406
 
407
c        Calculate layer pressures
408
         if (leveltype.eq.'hybrid_sigma_pressure' ) then
409
            do i=1,vardim(1)
410
              do j=1,vardim(2)
411
                 do k=1,vardim(3)
412
                  tmp3(i,j,k)=aktmp(k)+bktmp(k)*tmp2(i,j)
413
                 enddo
414
              enddo
415
           enddo
416
         elseif (leveltype.eq.'air_pressure' ) then
417
           do i=1,vardim(1)
418
              do j=1,vardim(2)
419
                 do k=1,vardim(3)
420
                  tmp3(i,j,k)=lev(k)
421
                 enddo
422
              enddo
423
           enddo
424
         endif
425
 
426
c        Get PS - close array on demand
427
         do j=1,vardim(2)
428
           do i=1,vardim(1)
429
             ps(i,j) = tmp2(i,j)
430
           enddo
431
           if (closear.eq.1) ps(vardim(1)+1,j) = ps(1,j)
432
         enddo
433
 
434
c        Get P3 - close array on demand + vertical swap
435
         do j=1,vardim(2)
436
           do k=1,vardim(3)
437
             do i=1,vardim(1)
438
               if ( vertical_swap.eq.1 ) then
439
                  p3(i,j,k) = tmp3(i,j,vardim(3)-k+1)
440
               else
441
                  p3(i,j,k) = tmp3(i,j,k)
442
               endif
443
             enddo
444
             if (closear.eq.1) p3(vardim(1)+1,j,k) = p3(1,j,k)
445
           enddo
446
         enddo
447
 
448
c        Get AK,BK - vertical swap on demand
449
         if ( leveltype.eq.'hybrid_sigma_pressure' ) then
450
           do k=1,vardim(3)
451
              if ( vertical_swap.eq.1 ) then
452
                 ak(k) = aktmp(vardim(3)-k+1)
453
                 bk(k) = bktmp(vardim(3)-k+1)
454
              else
455
                 ak(k) = aktmp(k)
456
                 bk(k) = bktmp(k)
457
              endif
458
           enddo
459
         elseif (leveltype.eq.'air_pressure' ) then
460
           do k=1,vardim(3)
461
              if ( vertical_swap.eq.1 ) then
462
                 ak(k) = lev(vardim(3)-k+1)
463
                 bk(k) = 0.
464
              else
465
                ak(k) = lev(k)
466
                bk(k) = 0.
467
              endif
468
           enddo
469
         endif
470
 
471
      endif
472
 
473
 
474
      return
475
 
476
      end
477
 
478
c     ------------------------------------------------------------
479
c     Read wind information
480
c     ------------------------------------------------------------
481
 
482
      subroutine input_wind (fid,fieldname,field,time,stagz,mdv,
483
     >                       xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz,
484
     >                       timecheck)
485
 
486
c     Read the wind component <fieldname> from the file with identifier
487
c     <fid> and save it in the 3d array <field>. The vertical staggering 
488
c     information is provided in <stagz> and gives the reference to either
489
c     the layer or level field from <input_grid>. A consistency check is
490
c     performed to have an agreement with the grid specified by <xmin,xmax,
491
c     ymin,ymax,dx,dy,nx,ny,nz>.
492
 
493
      use netcdf
494
 
495
      implicit none
496
 
497
c     Declaration of variables and parameters
498
      integer      fid                 ! File identifier
499
      character*80 fieldname           ! Name of the wind field
500
      integer      nx,ny,nz            ! Dimension of fields
501
      real         field(nx,ny,nz)     ! 3d wind field
502
      real         stagz               ! Staggering in the z direction
503
      real         mdv                 ! Missing data flag
504
      real         xmin,xmax,ymin,ymax ! Domain size
505
      real         dx,dy               ! Horizontal resolution
506
      real         time                ! Time
507
      character*80 timecheck           ! Either 'yes' or 'no'
508
 
509
c     Numerical and physical parameters
510
      real        eps                 ! Numerical epsilon
511
      parameter  (eps=0.001)
512
      real        notimecheck         ! 'Flag' for no time check
513
      parameter  (notimecheck=7.26537)
514
 
515
c     Netcdf variables
516
      integer      ierr
517
      character*80 varname
518
      integer      vardim(4)
519
      real         varmin(4),varmax(4)
520
      real         stag(4)
521
      integer      ndim
522
      real         times(10)
523
      integer      ntimes
524
      character*80 cstfile
525
      integer      cstid
526
      real         aklay(200),bklay(200),aklev(200),bklev(200)
527
      real         ps(nx,ny)
528
      integer      dimids (nf90_max_var_dims)
529
      character*80 dimname(nf90_max_var_dims)
530
      integer      varid
531
      integer      cdfid
532
      real,allocatable, dimension (:)     :: lon,lat,lev
533
      real,allocatable, dimension (:,:)   :: tmp2
534
      real,allocatable, dimension (:,:,:) :: tmp3
535
      real,allocatable, dimension (:)     :: aktmp,bktmp
536
      character*80  leveltype
537
      integer       vertical_swap
538
      character*80  units
539
      integer       nakbktmp
540
      integer       dimid
541
 
542
c     Auxiliary variables
543
      integer      isok
544
      integer      i,j,k
545
      integer      nz1
546
      real         rtime
547
      integer      closear
548
      integer      stat
549
      real         delta
550
      integer      pressure
551
 
552
c     Init mdv
553
      mdv = -999.
554
 
555
c     Special handling if 3D pressure is
556
      if ( fieldname.eq.'P' ) then
557
         fieldname = 'U'
558
         pressure  = 1
559
      else
560
         pressure = 0
561
      endif
562
 
563
c     Get the number of dimensions -> ndim
564
      ierr = NF90_INQ_VARID(fid,fieldname,varid)
565
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
566
      ierr = nf90_inquire_variable(fid, varid, ndims  = ndim)
567
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
568
 
569
c     Get the dimensions of the arrays -> varid(1:ndim)
570
      ierr = NF90_INQ_VARID(fid,fieldname,varid)
571
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
572
      ierr = nf90_inquire_variable(fid, varid, 
573
     >                                dimids = dimids(1:ndim))
574
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
575
      do i=1,ndim
576
        ierr = nf90_inquire_dimension(fid, dimids(i), 
577
     >                               name = dimname(i) )
578
        IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
579
        ierr = nf90_inquire_dimension(fid, dimids(i),len=vardim(i))
580
        IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
581
      enddo
582
 
583
c     Check whether the list of dimensions is OK
584
      if (ndim .eq. 4) then
585
          if ( ( dimname(1).ne.'lon'  ).or.
586
     >       ( dimname(2).ne.'lat'  ).or.
587
     >       ( dimname(3).ne.'lev'  ).and.( dimname(3).ne.'lev_2'  ).or.
588
     >         ( dimname(4).ne.'time' ) )
589
     >    then
590
        print*,' ERROR: the dimensions of the variable are not correct'
591
        print*,'        expected -> lon / lat / lev / time'
592
        print*, ( trim(dimname(i))//' / ',i=1,ndim )
593
            stop
594
          endif
595
      else 
596
          if ( ( dimname(1).ne.'lon'  ).or.
597
     >         ( dimname(2).ne.'lat'  ).or.
598
     >         ( dimname(3).ne.'time' ) )
599
     >    then
600
        print*,' ERROR: the dimensions of the variable are not correct'
601
        print*,'        expected -> lon / lat / time'
602
        print*, ( trim(dimname(i))//' / ',i=1,ndim )
603
            stop
604
          endif
605
      end if
606
 
607
c     Check about the type of vertical levels
608
      if (ndim .eq. 4) then
609
 
610
c         Get dimension of AK,BK
611
          varname = 'nhym'
612
          ierr = NF90_INQ_DIMID(fid,varname,dimid)
613
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
614
          ierr = nf90_inquire_dimension(fid, dimid,len=nakbktmp)
615
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
616
 
617
          varname=dimname(3)
618
          ierr = NF90_INQ_VARID(fid,varname,varid)
619
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
620
          ierr = nf90_get_att(fid, varid, "standard_name", leveltype)
621
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
622
          if ( (leveltype.ne.'hybrid_sigma_pressure').and.
623
     >         (leveltype.ne.'air_pressure'         ) ) then
624
             print*,' ERROR: input netCDF data must be on hybrid-sigma'
625
             print*,'        or air pressure levels!',trim(leveltype)
626
             stop
627
          endif
628
      else
629
         leveltype='air_pressure'
630
      endif
631
 
632
c     Allocate memory for reading arrays - depending on <closear>
633
      allocate(tmp2(vardim(1),vardim(2)),stat=stat)
634
      if (stat.ne.0) print*,'*** error allocating array tmp2     ***'
635
      allocate(tmp3(vardim(1),vardim(2),vardim(3)),stat=stat)
636
      if (stat.ne.0) print*,'*** error allocating array tmp3     ***'
637
      allocate(lon(vardim(1)),stat=stat)
638
      if (stat.ne.0) print*,'*** error allocating array lon     ***'
639
      allocate(lat(vardim(2)),stat=stat)
640
      if (stat.ne.0) print*,'*** error allocating array lat     ***'
641
      allocate(lev(vardim(3)),stat=stat)
642
      if (stat.ne.0) print*,'*** error allocating array lev     ***'
643
      if (ndim .eq. 4) then
644
          allocate(aktmp(nakbktmp),stat=stat)
645
          if (stat.ne.0) print*,'*** error allocating array aktmp   ***'
646
          allocate(bktmp(nakbktmp),stat=stat)
647
          if (stat.ne.0) print*,'*** error allocating array bktmp   ***'
648
      end if
649
 
650
c     Get domain boundaries - longitude, latitude, levels
651
      varname = dimname(1)
652
      ierr = NF90_INQ_VARID(fid,varname,varid)
653
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
654
      ierr = nf90_get_var(fid,varid,lon)
655
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
656
      varname = dimname(2)
657
      ierr = NF90_INQ_VARID(fid,varname,varid)
658
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
659
      ierr = nf90_get_var(fid,varid,lat)
660
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
661
      varname = dimname(3)
662
      ierr = NF90_INQ_VARID(fid,varname,varid)
663
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
664
      ierr = nf90_get_var(fid,varid,lev)
665
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
666
      varmin(1) = lon(1)
667
      varmax(1) = lon( vardim(1) )
668
      varmin(2) = lat(1)
669
      varmax(2) = lat( vardim(2) )
670
 
671
c     Get ak and bk
672
      if (ndim .eq. 4) then
673
          varname='hyam'
674
          ierr = NF90_INQ_VARID(fid,varname,varid)
675
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
676
          ierr = nf90_get_var(fid,varid,aktmp)
677
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
678
          varname='hybm'
679
          ierr = NF90_INQ_VARID(fid,varname,varid)
680
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
681
          ierr = nf90_get_var(fid,varid,bktmp)
682
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
683
 
684
c         Check that unit of ak is in hPa - if necessary correct it
685
          varname='hyam'
686
          ierr = NF90_INQ_VARID(fid,varname,varid)
687
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
688
          ierr = nf90_get_att(fid, varid, "units", units)
689
          IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
690
          if ( units.eq.'Pa' ) then
691
             do k=1,nakbktmp
692
                aktmp(k) = 0.01 * aktmp(k)
693
             enddo
694
          endif
695
      end if
696
 
697
c     Check that unit of lev is in hPa - if necessary correct it
698
      if ( leveltype.eq.'air_pressure' .and. vardim(3) .gt. 1) then
699
         varname='lev'
700
         ierr = NF90_INQ_VARID(fid,varname,varid)
701
         IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
702
         ierr = nf90_get_att(fid, varid, "units", units)
703
         IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
704
         if ( units.eq.'Pa' ) then
705
            do k=1,vardim(3)
706
               lev(k) = 0.01 * lev(k)
707
            enddo
708
         endif
709
      endif
710
 
711
c     Decide whether to swap vertical levels
712
      vertical_swap = 1
713
      if ( leveltype.eq.'hybrid_sigma_pressure') then
714
        if ( (aktmp(1) + bktmp(1) * 1000.).gt.
715
     >       (aktmp(2) + bktmp(2) * 1000.) )
716
     >  then
717
          vertical_swap = 0
718
        endif
719
      elseif ( leveltype.eq.'air_pressure') then
720
        if ( lev(1).gt.lev(2) ) then
721
          vertical_swap = 0
722
        endif
723
      endif
724
 
725
c     Read data /or set 3D pressure field) 
726
      if ( pressure.eq.0 ) then
47 michaesp 727
         if ( vardim(3).gt.1 ) then
728
           ierr = NF90_INQ_VARID(fid,fieldname,varid)
729
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
730
           ierr = nf90_get_var(fid,varid,tmp3)
731
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
732
         else
733
           ierr = NF90_INQ_VARID(fid,fieldname,varid)
734
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
735
           ierr = nf90_get_var(fid,varid,tmp2)
736
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
737
         endif 
46 michaesp 738
      else
739
         if (leveltype.eq.'hybrid_sigma_pressure' ) then
740
            do i=1,vardim(1)
741
              do j=1,vardim(2)
742
                 do k=1,vardim(3)
743
                  tmp3(i,j,k)=aktmp(k)+bktmp(k)*tmp2(i,j)
744
                 enddo
745
              enddo
746
           enddo
747
         elseif (leveltype.eq.'air_pressure' ) then
748
           do i=1,vardim(1)
749
              do j=1,vardim(2)
750
                 do k=1,vardim(3)
751
                  tmp3(i,j,k)=lev(k)
752
                 enddo
753
              enddo
754
           enddo
755
         endif
756
      endif
47 michaesp 757
 
46 michaesp 758
c     If the field is 2D, expand it to 3D - simple handling of 2D tracing
47 michaesp 759
      if ( vardim(3).eq.1 ) then
760
         do i=1,vardim(1)
761
            do j=1,vardim(2)
762
               tmp3(i,j,1) = tmp2(i,j)
763
            enddo
764
         enddo
765
      endif
46 michaesp 766
 
767
c     Decide whether to close arrays
768
      delta = varmax(1)-varmin(1)-360.
769
      if (abs(delta+dx).lt.eps) then
770
          closear = 1
771
      else
772
          closear = 0
773
      endif
774
 
775
c     Save output array - close array and swap on demand
776
 
777
      do j=1,vardim(2)
778
        do k=1,nz
779
          do i=1,vardim(1)
780
             if (ndim .eq. 4) then
781
                 if ( vertical_swap.eq.1 ) then
782
                     field(i,j,k) = tmp3(i,j,vardim(3)-k+1)
783
                 else
784
                     field(i,j,k) = tmp3(i,j,k)
785
                 endif
786
             else 
787
                field(i,j,k) = tmp3(i,j,1)
788
             endif
789
          enddo
790
          if (closear.eq.1) field(vardim(1)+1,j,k) = field(1,j,k)
791
        enddo
792
      enddo
793
 
794
c     Exit point
795
      return
796
 
797
      end
798
 
799
 
800
c     ------------------------------------------------------------
801
c     Close input file
802
c     ------------------------------------------------------------
803
 
804
      subroutine input_close(fid)
805
 
806
c     Close the input file with file identifier <fid>.
807
 
808
      use netcdf
809
 
810
      implicit none
811
 
812
c     Declaration of subroutine parameters
813
      integer fid
814
 
815
c     Auxiliary variables
816
      integer ierr
817
 
818
c     Close file
819
      ierr = NF90_CLOSE(fid)
820
      IF( ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
821
 
822
      end
823
 
824
c     ------------------------------------------------------------
825
c     Get a list of variables on netCDF file
826
c     ------------------------------------------------------------
827
 
828
      subroutine input_getvars(fid,vnam,nvars)
829
 
830
c     List of variables on netCDF file
831
 
832
      use netcdf
833
 
834
      implicit none
835
 
836
c     Declaration of subroutine parameters
837
      integer      fid
838
      integer      nvars
839
      character*80 vnam(200)
840
 
841
c     Auxiliary variables
842
      integer ierr
843
      integer i
844
      integer nDims,nGlobalAtts,unlimdimid
845
 
846
      ierr = nf90_inquire(fid, nDims, nVars, nGlobalAtts, unlimdimid)
847
      IF( ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
848
 
849
      do i=1,nVars
850
         ierr = nf90_inquire_variable(fid, i, name = vnam(i))
851
      enddo
852
 
853
      end