Subversion Repositories lagranto.um

Rev

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

Rev Author Line No. Line
3 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
 
7 michaesp 34
      use netcdf
35
 
3 michaesp 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
 
7 michaesp 45
c     Open netcdf file
46
      ierr = NF90_OPEN(TRIM(filename),nf90_nowrite, fid)
47
      IF ( ierr /= nf90_NoErr ) PRINT *,NF90_STRERROR(ierr)
48
 
3 michaesp 49
c     Exception handling
50
      return
51
 
52
 900  print*,'Cannot open input file ',trim(filename)
53
      stop
54
 
55
      end
56
 
57
 
58
c     ------------------------------------------------------------
59
c     Read information about the grid
60
c     ------------------------------------------------------------
61
 
62
      subroutine input_grid 
63
     >                   (fid,fieldname,xmin,xmax,ymin,ymax,dx,dy,nx,ny,
64
     >                    time,pollon,pollat,p3,ps,nz,ak,bk,stagz,
65
     >                    timecheck)
66
 
67
c     Read grid information at <time> from file with identifier <fid>. 
68
c     The horizontal grid is characterized by <xmin,xmax,ymin,ymax,dx,dy>
69
c     with pole position at <pollon,pollat> and grid dimension <nx,ny>.
70
c     The 3d arrays <p3(nx,ny,nz)> gives the vertical coordinates, either
71
c     on the staggered or unstaggered grid (with <stagz> as the flag).
72
c     The surface pressure is given in <ps(nx,ny)>. If <fid> is negative, 
73
c     only the grid dimensions and grid parameters (xmin...pollat,nz) are 
74
c     determined and returned (this is needed for dynamical allocation of 
75
c     memory).
76
 
7 michaesp 77
      use netcdf
78
 
3 michaesp 79
      implicit none
80
 
81
c     Declaration of subroutine parameters 
82
      integer      fid                 ! File identifier
83
      real         xmin,xmax,ymin,ymax ! Domain size
84
      real         dx,dy               ! Horizontal resolution
85
      integer      nx,ny,nz            ! Grid dimensions
86
      real         pollon,pollat       ! Longitude and latitude of pole
87
      real         p3(nx,ny,nz)        ! Staggered levels
88
      real         ps(nx,ny)           ! Surface pressure
89
      real         time                ! Time of the grid information
90
      real         ak(nz),bk(nz)       ! Ak and Bk for layers or levels
91
      real         stagz               ! Vertical staggering (0 or -0.5)
92
      character*80 fieldname           ! Variable from which to take grid info
93
      character*80 timecheck           ! Either 'yes' or 'no'
94
 
95
c     Numerical and physical parameters
96
      real          eps                 ! Numerical epsilon
97
      parameter    (eps=0.001)
98
 
99
c     Netcdf variables
100
      integer      vardim(4)
101
      real         varmin(4),varmax(4)
102
      real         mdv
103
      real         stag(4)
104
      integer      ndim
105
      character*80 cstfile
106
      integer      cstid
7 michaesp 107
      real         times
3 michaesp 108
      integer      ntimes
109
      real         aklay(nz),bklay(nz),aklev(nz),bklev(nz)
110
      integer      nvars
111
      character*80 vars(100)
7 michaesp 112
      integer        dimids (nf90_max_var_dims)
113
      character*80   dimname(nf90_max_var_dims)
3 michaesp 114
 
115
c     Auxiliary varaibles
116
      integer      ierr       
117
      integer      i,j,k
118
      integer      isok
119
      real         tmp(200)
120
      character*80 varname
121
      real         rtime
7 michaesp 122
      integer      varid
123
      integer      cdfid
11 michaesp 124
      real         rmax,rmin
3 michaesp 125
 
7 michaesp 126
c     Set file identifier
3 michaesp 127
      if (fid.lt.0) then
7 michaesp 128
        cdfid = -fid
129
      else 
130
        cdfid = fid
131
      endif
132
 
133
c     Get varid
134
      ierr = NF90_INQ_VARID(cdfid,fieldname,varid)
135
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
136
 
137
c     Get numebr of dimensions -> ndim      
138
      ierr = nf90_inquire_variable(cdfid, varid, ndims  = ndim)
139
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
140
 
141
c     Get dim IDs         
142
      ierr = nf90_inquire_variable(cdfid, varid, 
143
     >                                   dimids = dimids(1:ndim))
144
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
3 michaesp 145
 
7 michaesp 146
c     Get dimensions -> vardim(1:ndim)         
147
      do i=1,ndim
148
           ierr = nf90_inquire_dimension(cdfid, dimids(i), 
149
     >                               name = dimname(i) )
150
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
151
           ierr = nf90_inquire_dimension(cdfid, dimids(i),len=vardim(i))
152
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
153
      enddo
154
 
155
c     Get domain min -> varmin(1:3)        
156
      ierr  = nf90_get_att(cdfid, varid, "xmin", varmin(1))
157
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
158
      ierr  = nf90_get_att(cdfid, varid, "ymin", varmin(2))
159
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
160
      ierr  = nf90_get_att(cdfid, varid, "zmin", varmin(3))
161
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
162
 
163
c     Get domain max -> varmax(1:3)     
164
      ierr  = nf90_get_att(cdfid, varid, "xmax", varmax(1))
165
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
166
      ierr  = nf90_get_att(cdfid, varid, "ymax", varmax(2))
167
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
168
      ierr  = nf90_get_att(cdfid, varid, "zmax", varmax(3))
169
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
170
 
171
c     Get vertical staggering -> stagz           
172
      ierr  = nf90_get_att(cdfid, varid, "zstag", stagz)
173
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
174
 
175
c     Get missing data value -> mdv         
176
      ierr  = nf90_get_att(cdfid, varid, "missing_value", mdv)
177
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
3 michaesp 178
 
7 michaesp 179
c     Set the grid dimensions and constants
180
      nx   = vardim(1)
181
      ny   = vardim(2)
182
      nz   = vardim(3)
183
      xmin = varmin(1)
184
      ymin = varmin(2)
185
      xmax = varmax(1)
186
      ymax = varmax(2)
187
      dx   = (xmax-xmin)/real(nx-1)
188
      dy   = (ymax-ymin)/real(ny-1)
3 michaesp 189
 
7 michaesp 190
c     We want the longitudes within -180 ... + 180
191
      if ( xmin.lt.-180.) then
3 michaesp 192
            xmin = xmin + 360.
193
            xmax = xmax + 360.
7 michaesp 194
      else if ( xmax.gt.360. ) then
3 michaesp 195
            xmin = xmin - 360.
196
            xmax = xmax - 360.
7 michaesp 197
      endif
3 michaesp 198
 
7 michaesp 199
c     Get name of constants file -> cstfile
200
      ierr  = nf90_get_att(cdfid,nf90_global,
201
     >                    "constants_file_name ", cstfile )
202
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
3 michaesp 203
 
7 michaesp 204
c     Get pole position from constants file
205
      ierr = NF90_OPEN(TRIM(cstfile),nf90_nowrite, cstid)
206
      IF ( ierr /= nf90_NoErr ) PRINT *,NF90_STRERROR(ierr)
207
      varname='pollon'
208
      ierr = NF90_INQ_VARID(cstid,varname,varid)
209
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
210
      ierr = nf90_get_var(cstid,varid,pollon)
211
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
212
      varname='pollat'
213
      ierr = NF90_INQ_VARID(cstid,varname,varid)
214
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
215
      ierr = nf90_get_var(cstid,varid,pollat)
216
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
217
      ierr = NF90_CLOSE(cstid)
218
      IF( ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
219
 
220
c     Skip the rest if fid < 0: 
221
      if ( fid.lt.0 ) goto 900      
222
 
223
c     Get ak and bk from constants file
224
      ierr = NF90_OPEN(TRIM(cstfile),nf90_nowrite, cstid)
225
      IF ( ierr /= nf90_NoErr ) PRINT *,NF90_STRERROR(ierr)
226
      varname='aklev'
227
      ierr = NF90_INQ_VARID(cstid,varname,varid)
228
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
229
      ierr = nf90_get_var(cstid,varid,aklev)
230
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
231
      varname='bklev'
232
      ierr = NF90_INQ_VARID(cstid,varname,varid)
233
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
234
      ierr = nf90_get_var(cstid,varid,bklev)
235
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
236
      varname='aklay'
237
      ierr = NF90_INQ_VARID(cstid,varname,varid)
238
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
239
      ierr = nf90_get_var(cstid,varid,aklay)
240
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
241
      varname='bklay'
242
      ierr = NF90_INQ_VARID(cstid,varname,varid)
243
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
244
      ierr = nf90_get_var(cstid,varid,bklay)
245
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
246
      ierr = NF90_CLOSE(cstid)
247
      IF( ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
248
 
249
c     print*,'AKLEV : '
250
c     print*, (aklev(i),i=1,20)
251
c     print*,'BKLEV : '
252
c     print*,(bklev(i),i=1,20)
253
c     print*,'AKLAY : '
254
c     print*,(aklay(i),i=1,20)
255
c     print*,'BKLAY : '
256
c     print*,(bklay(i),i=1,20)
257
 
258
c     Get time information (check if time is correct)
259
      varname = 'time'
260
      ierr = NF90_INQ_VARID(cdfid,varname,varid)
261
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
262
      ierr = nf90_get_var(cdfid,varid,times)
263
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
264
      isok=0
265
      if (abs(time-times).lt.eps) then
3 michaesp 266
               isok = 1
7 michaesp 267
               rtime = times
268
      elseif (timecheck.eq.'no') then
3 michaesp 269
               isok = 1
7 michaesp 270
               rtime = times
271
      endif
272
      if ( isok.eq.0 ) then
273
         print*,' ERROR: time ',rtime,' not found on netCDF file' 
274
         stop
275
      endif
276
 
277
c     print*,'TIME : ',rtime
3 michaesp 278
 
7 michaesp 279
c     Read surface pressure
280
      varname='PS'
281
      ierr = NF90_INQ_VARID(cdfid,varname,varid)
282
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
283
      ierr = nf90_get_var(cdfid,varid,ps)
284
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
11 michaesp 285
 
286
c     Check that PS is in hPa - quick and dirty
287
      rmax = -1.e9
288
      rmin = +1.e9
289
      do i=1,nx
290
       do j=1,ny
291
        if ( (ps(i,j).gt.rmax).and.abs(ps(i,j)-mdv).gt.eps)  then
292
          rmax = ps(i,j)
293
        endif
294
        if ( (ps(i,j).lt.rmin).and.abs(ps(i,j)-mdv).gt.eps)  then
295
          rmin = ps(i,j)
296
        endif
297
       enddo
298
      enddo
299
      if ( (rmin.lt.200.).or.(rmax.gt.1500.) ) then
300
        print*,' ERROR: PS must be in hPa... Stop'
301
        stop
302
      endif
7 michaesp 303
 
304
c     Calculate layer and level pressures
305
      do i=1,nx
306
         do j=1,ny
3 michaesp 307
               do k=1,nz
308
                  if ( abs(stagz).lt.eps ) then
309
                     p3(i,j,k)=aklev(k)+bklev(k)*ps(i,j)
310
                  else
311
                     p3(i,j,k)=aklay(k)+bklay(k)*ps(i,j)
312
                  endif
313
               enddo
314
         enddo
7 michaesp 315
      enddo
3 michaesp 316
 
7 michaesp 317
c     Set the ak and bk for the vertical grid
318
      do k=1,nz
3 michaesp 319
            if ( abs(stagz).lt.eps ) then
320
               ak(k)=aklev(k)
321
               bk(k)=bklev(k)
322
            else
323
               ak(k)=aklay(k)
324
               bk(k)=bklay(k)
325
            endif
7 michaesp 326
      enddo
3 michaesp 327
 
7 michaesp 328
c     Exit point
329
 900  continue    
330
 
3 michaesp 331
      return
332
 
333
      end
334
 
335
c     ------------------------------------------------------------
336
c     Read wind information
337
c     ------------------------------------------------------------
338
 
339
      subroutine input_wind (fid,fieldname,field,time,stagz,mdv,
340
     >                       xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz,
341
     >                       timecheck)
342
 
343
c     Read the wind component <fieldname> from the file with identifier
344
c     <fid> and save it in the 3d array <field>. The vertical staggering 
345
c     information is provided in <stagz> and gives the reference to either
346
c     the layer or level field from <input_grid>. A consistency check is
347
c     performed to have an agreement with the grid specified by <xmin,xmax,
348
c     ymin,ymax,dx,dy,nx,ny,nz>.
349
 
7 michaesp 350
      use netcdf
351
 
3 michaesp 352
      implicit none
353
 
354
c     Declaration of variables and parameters
355
      integer      fid                 ! File identifier
356
      character*80 fieldname           ! Name of the wind field
357
      integer      nx,ny,nz            ! Dimension of fields
358
      real         field(nx,ny,nz)     ! 3d wind field
359
      real         stagz               ! Staggering in the z direction
360
      real         mdv                 ! Missing data flag
361
      real         xmin,xmax,ymin,ymax ! Domain size
362
      real         dx,dy               ! Horizontal resolution
363
      real         time                ! Time
364
      character*80 timecheck           ! Either 'yes' or 'no'
365
 
366
c     Numerical and physical parameters
367
      real        eps                 ! Numerical epsilon
368
      parameter  (eps=0.001)
369
      real        notimecheck         ! 'Flag' for no time check
370
      parameter  (notimecheck=7.26537)
371
 
372
c     Netcdf variables
373
      integer      ierr
374
      character*80 varname
375
      integer      vardim(4)
376
      real         varmin(4),varmax(4)
377
      real         stag(4)
378
      integer      ndim
379
      real         times(10)
380
      integer      ntimes
381
      character*80 cstfile
382
      integer      cstid
383
      real         aklay(200),bklay(200),aklev(200),bklev(200)
384
      real         ps(nx,ny)
7 michaesp 385
      integer      dimids (nf90_max_var_dims)
386
      character*80 dimname(nf90_max_var_dims)
387
      integer      varid
388
      integer      cdfid
3 michaesp 389
 
390
c     Auxiliary variables
391
      integer      isok
392
      integer      i,j,k
393
      integer      nz1
394
      real         rtime
395
 
7 michaesp 396
c     Get varid
397
      ierr = NF90_INQ_VARID(fid,fieldname,varid)
398
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
399
 
400
c     Get number of vertical levels -> vardim(3)    
401
      ierr = nf90_inquire_variable(fid, varid, ndims  = ndim)
402
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
403
      ierr = nf90_inquire_variable(fid, varid, 
404
     >                                   dimids = dimids(1:ndim))
405
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
406
      do i=1,ndim
407
           ierr = nf90_inquire_dimension(fid, dimids(i), 
408
     >                               name = dimname(i) )
409
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
410
           ierr = nf90_inquire_dimension(fid, dimids(i),len=vardim(i))
411
           IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
3 michaesp 412
      enddo
413
 
7 michaesp 414
c     Read data 
415
      varname=fieldname
416
      ierr = nf90_get_var(fid,varid,field)
417
      IF(ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
418
 
3 michaesp 419
c     If the field is 2D, expand it to 3D - simple handling of 2D tracing
420
      if ( vardim(3).eq.1 ) then
421
         do i=1,nx
422
            do j=1,ny
423
               do k=1,nz
424
                  field(i,j,k) = field(i,j,1)
425
               enddo
426
            enddo
427
         enddo
428
      endif
429
 
7 michaesp 430
c     Exit point
3 michaesp 431
      return
7 michaesp 432
 
3 michaesp 433
      end
434
 
435
c     ------------------------------------------------------------
436
c     Close input file
437
c     ------------------------------------------------------------
438
 
439
      subroutine input_close(fid)
440
 
441
c     Close the input file with file identifier <fid>.
442
 
7 michaesp 443
      use netcdf
444
 
3 michaesp 445
      implicit none
446
 
447
c     Declaration of subroutine parameters
448
      integer fid
449
 
450
c     Auxiliary variables
451
      integer ierr
452
 
453
c     Close file
7 michaesp 454
      ierr = NF90_CLOSE(fid)
455
      IF( ierr /= nf90_NoErr) PRINT *,NF90_STRERROR(ierr)
456
 
3 michaesp 457
      end