Subversion Repositories pvinversion.ecmwf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 michaesp 1
      PROGRAM pv_to_qgpv
2
 
3
c     ********************************************************************************
4
c     * TRANSFORM ERTEL'S PV TO QUASI-GEOSTROPHIC PV                                 *
5
c     * Rene Fehlmann 1994 / Code re-organization: Michael Sprenger, 2006            *
6
c     ********************************************************************************
7
 
8
c     --------------------------------------------------------------------------------
9
c     Declaration of variables, parameters, externals and common blocks
10
c     --------------------------------------------------------------------------------
11
 
12
      implicit none
13
 
14
c     Input and output file
15
      character*80   pvsrcfile
16
      character*80   referfile
17
      character*80   anomafile
18
 
19
c     Grid parameters
20
      integer        nx,ny,nz
21
      real           xmin,ymin,zmin,xmax,ymax,zmax
22
      real           dx,dy,dz
23
      real           mdv
24
 
25
c     Numerical and physical parameters
26
      real           pi180                           ! Pi/180
27
      parameter      (pi180=3.141592654/180.)
28
      real           rerd                            ! Earth's radius
29
      parameter      (rerd=6.371229e6)
30
      real           eps                             ! Numerical epsilon
31
      parameter      (eps=0.01)
32
      real           scale                           ! Scale for PV unit
33
      parameter      (scale=1e6)
34
      real           minagl                          ! No PV and qgPV below this height AGL
35
      parameter      (minagl=1000.)
36
 
37
c     Reference state and grid parameters
38
      real,   allocatable,dimension (:)   :: nsqref
39
      real,   allocatable,dimension (:)   :: thetaref
40
      real,   allocatable,dimension (:)   :: rhoref
41
      real,   allocatable,dimension (:)   :: pressref
42
      real,   allocatable,dimension (:)   :: zref
43
      real,   allocatable,dimension (:,:) :: coriol
44
      real,   allocatable,dimension (:,:) :: oro
45
      real    deltax,deltay,deltaz
46
 
47
c     3d fields for calculation of qgPV and Ertel's PV
48
      real,allocatable,dimension (:,:,:) :: qgpv,pv1,pv2,pv
49
 
50
c     Auxiliary variables
51
      real         zpos
52
      integer      i,j,k
53
      integer      stat
54
      character*80 varname
55
      integer      istep
56
      real         mean,rmsq,min,max
57
      integer      step
58
      real,allocatable,dimension (:,:) :: tmp
59
 
60
c     --------------------------------------------------------------------------------
61
c     Input
62
c     --------------------------------------------------------------------------------
63
 
64
      print*,'********************************************************'
65
      print*,'* PV_TO_QGPV                                           *'
66
      print*,'********************************************************'
67
 
68
 
69
c     Read parameter file
70
      open(10,file='fort.10')
71
       read(10,*) pvsrcfile
72
       read(10,*) referfile
73
       read(10,*) anomafile
74
      close(10) 
75
      print*
76
      print*,trim(pvsrcfile)
77
      print*,trim(referfile)
78
      print*,trim(anomafile)
79
      print*
80
 
81
c     Get lat/lon gid parameters from input file
82
      call read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,
83
     >               pvsrcfile)
84
      print*,'Read_Dim: nx,ny,nz         = ',nx,ny,nz
85
      print*,'          dx,dy,dz         = ',dx,dy,dz
86
      print*,'          xmin,ymin,zmin   = ',xmin,ymin,zmin
87
      print*,'          mdv              = ',mdv
88
      print*
89
 
90
c     Count from 0, not from 1: consistent with <inv_cart.f>.
91
      nx=nx-1
92
      ny=ny-1
93
      nz=nz-1
94
 
95
c     Allocate memory for reference profile and grid parameters
96
      allocate(rhoref  (0:2*nz),STAT=stat)
97
      if (stat.ne.0) print*,'error allocating rhoref'
98
      allocate(pressref(0:2*nz),STAT=stat)
99
      if (stat.ne.0) print*,'error allocating pressref'
100
      allocate(thetaref(0:2*nz),STAT=stat)
101
      if (stat.ne.0) print*,'error allocating thetaref'
102
      allocate(nsqref  (0:2*nz),STAT=stat)
103
      if (stat.ne.0) print*,'error allocating nsqref'
104
      allocate(zref    (0:2*nz),STAT=stat)
105
      if (stat.ne.0) print*,'error allocating zref'
106
      allocate(coriol  (0:nx,0:ny),STAT=stat)
107
      if (stat.ne.0) print*,'error allocating coriol'
108
      allocate(oro     (0:nx,0:ny),STAT=stat)
109
      if (stat.ne.0) print*,'error allocating oro'
110
 
111
 
112
c     Allocate memory for calculation of qgPV and Ertel's PV
113
      allocate(pv1 (0:nx,0:ny,0:nz),STAT=stat)
114
      if (stat.ne.0) print*,'error allocating pv1'
115
      allocate(pv2 (0:nx,0:ny,0:nz),STAT=stat)
116
      if (stat.ne.0) print*,'error allocating pv2'
117
      allocate(pv  (0:nx,0:ny,0:nz),STAT=stat)
118
      if (stat.ne.0) print*,'error allocating pv'      
119
      allocate(qgpv(0:nx,0:ny,0:nz),STAT=stat)
120
      if (stat.ne.0) print*,'error allocating qgpv'
121
 
122
c     Allocate memory for temporary array
123
      allocate(tmp(0:nx,0:ny),STAT=stat)
124
      if (stat.ne.0) print*,'error allocating tmp'
125
 
126
c     --------------------------------------------------------------------------------
127
c     Calculate the qgPV from Ertel's PV and put it onto file
128
c     --------------------------------------------------------------------------------
129
 
130
c     Read data from file
131
      varname='PV'
132
      call read_inp (pv1,varname,pvsrcfile,
133
     >               nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
134
      varname='PV_AIM'
135
      call read_inp (pv2,varname,pvsrcfile,
136
     >               nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
137
 
138
c     Read reference profile and grid parameters
139
      call read_ref (nsqref,rhoref,thetaref,pressref,zref,
140
     >               nx,ny,nz,deltax,deltay,deltaz,coriol,oro,
141
     >               referfile)
142
 
143
c     If the PV is negative, set it to zero
144
      do i=0,nx
145
         do j=0,ny
146
            do k=0,nz
147
               if (pv1(i,j,k).lt.0.) pv1(i,j,k)=0.
148
               if (pv2(i,j,k).lt.0.) pv2(i,j,k)=0.
149
            enddo
150
         enddo
151
      enddo
152
 
153
c     Get the difference of Ertel's PV and set all missing values to 0
154
      do i=0,nx
155
         do j=0,ny
156
            do k=0,nz
157
               if ((abs(pv1(i,j,k)-mdv).gt.eps).and.
158
     >             (abs(pv2(i,j,k)-mdv).gt.eps)) then
159
                  pv(i,j,k)=pv1(i,j,k)-pv2(i,j,k)
160
               else
161
                  pv(i,j,k)=0.
162
               endif
163
            enddo
164
         enddo
165
      enddo
166
 
167
c     Calculate qgPV
168
      call epv_to_qgpv (qgpv,pv,
169
     >                  rhoref,pressref,nsqref,thetaref,
170
     >                  nx,ny,nz,mdv)
171
 
172
c     Set values on the boundaries to zero
173
      do i=0,nx
174
         do j=0,ny
175
            qgpv(i,j, 0)=0.
176
            qgpv(i,j,nz)=0.
177
         enddo
178
      enddo
179
      do i=0,nx
180
         do k=0,nz
181
            qgpv(i, 0,k)=0.
182
            qgpv(i,ny,k)=0.
183
         enddo
184
      enddo
185
      do j=0,ny
186
         do k=0,nz
187
            qgpv( 0,j,k)=0.
188
            qgpv(nx,j,k)=0.
189
         enddo
190
      enddo
191
 
192
c     Set all values to zero which are too near to the surface
193
      do i=0,nx
194
         do j=0,ny
195
            do k=0,nz
196
               zpos=zmin+real(k)*dz
197
               if (zpos.lt.(oro(i,j)+minagl)) then
198
                  pv(i,j,k)=0.
199
                  qgpv(i,j,k)=0.
200
               endif
201
            enddo
202
         enddo
203
      enddo
204
 
205
c     Write result to netcdf file
206
      varname='QGPV'
207
      call write_inp (qgpv,varname,anomafile,nx,ny,nz)
208
      varname='PV'
209
      call write_inp (pv,varname,anomafile,nx,ny,nz)
210
 
211
c     Write some info
212
      print*
213
      print*,'PV -> qgPV:     k    z     min     max    mean      rmsq'
214
      step=nz/10
215
      if (step.lt.1) step=1
216
      do k=0,nz,step
217
         do i=0,nx
218
            do j=0,ny
219
               tmp(i,j)=qgpv(i,j,k)
220
            enddo
221
         enddo
222
         call calc_error(min,max,mean,rmsq,tmp,nx,ny)
223
         write(*,'(8x,i3,f10.1,4f10.2)')
224
     >             k,zmin+real(k)*dz,scale*min,scale*max,
225
     >                               scale*mean,scale*rmsq
226
      enddo
227
      print*         
228
 
229
c     --------------------------------------------------------------------------------
230
c     Format specifications
231
c     --------------------------------------------------------------------------------
232
 
233
 111  format (5f20.9)
234
 106  format (2f20.9)
235
 
236
      end
237
 
238
 
239
c     ********************************************************************************
240
c     * NETCDF INPUT AND OUTPUT                                                      *
241
c     ********************************************************************************
242
 
243
c     --------------------------------------------------------------------------------
244
c     Write input field to netcdf
245
c     --------------------------------------------------------------------------------
246
 
247
      SUBROUTINE write_inp (field,fieldname,pvsrcfile,nx,ny,nz)
248
 
249
c     Read <fieldname> from netcdf file <pvsrcfile> into <field>. The grid is specified 
250
c     by <nx,ny,nz,dx,dy,dz,xmin,ymin,zmin>. A check is performed whether the input 
251
c     files are consitent with this grid. 
252
 
253
      implicit   none
254
 
255
c     Declaration of subroutine parameters
256
      integer              nx,ny,nz
257
      real                 field (0:nx,0:ny,0:nz)
258
      character*80         fieldname
259
      character*80         pvsrcfile
260
 
261
c     Auxiliary variables
262
      integer              cdfid,stat
263
      integer              vardim(4)
264
      real                 misdat
265
      real                 varmin(4),varmax(4),stag(4)
266
      integer              ndimin,outid,i,j,k
267
      real                 tmp(0:nx,0:ny,0:nz)
268
      integer              ntimes
269
      real                 time(200)       
270
      integer              nvars
271
      character*80         vnam(100),varname
272
      integer              isok
273
 
274
c     Get grid parameters from PV
275
      call cdfopn(pvsrcfile,cdfid,stat)
276
      if (stat.ne.0) goto 998
277
      call getvars(cdfid,nvars,vnam,stat)
278
      if (stat.ne.0) goto 998
279
      isok=0
280
      varname='PV'
281
      call check_varok(isok,varname,vnam,nvars)
282
      if (isok.eq.0) goto 998
283
      call getdef(cdfid,varname,ndimin,misdat,vardim,
284
     >            varmin,varmax,stag,stat)    
285
      if (stat.ne.0) goto 998
286
      time(1)=0.
287
      call gettimes(cdfid,time,ntimes,stat)  
288
      if (stat.ne.0) goto 998
289
      call clscdf(cdfid,stat)
290
      if (stat.ne.0) goto 998
291
 
292
c     Save variables (write definition, if necessary)
293
      call cdfwopn(pvsrcfile,cdfid,stat)
294
      if (stat.ne.0) goto 998
295
      isok=0
296
      varname=fieldname
297
      call check_varok(isok,varname,vnam,nvars)
298
      if (isok.eq.0) then
299
         call putdef(cdfid,varname,ndimin,misdat,vardim,
300
     >               varmin,varmax,stag,stat)
301
         if (stat.ne.0) goto 998
302
      endif
303
      call putdat(cdfid,varname,time(1),0,field,stat)
304
      print*,'W ',trim(varname),' ',trim(pvsrcfile)
305
      if (stat.ne.0) goto 998
306
 
307
c     Close input netcdf file
308
      call clscdf(cdfid,stat)
309
      if (stat.ne.0) goto 998
310
 
311
      return
312
 
313
c     Exception handling
314
 998  print*,'Write_Inp: Problem with input netcdf file... Stop'
315
      stop
316
 
317
      end
318
 
319
 
320
c     --------------------------------------------------------------------------------
321
c     Read input fields for reference profile
322
c     --------------------------------------------------------------------------------
323
 
324
      SUBROUTINE read_inp (field,fieldname,pvsrcfile,
325
     >                     nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv)
326
 
327
c     Read <fieldname> from netcdf file <pvsrcfile> into <field>. The grid is specified 
328
c     by <nx,ny,nz,dx,dy,dz,xmin,ymin,zmin>. A check is performed whether the input 
329
c     files are consitent with this grid. The missing data value is set to <mdv>.
330
 
331
      implicit   none
332
 
333
c     Declaration of subroutine parameters
334
      integer              nx,ny,nz
335
      real                 field(0:nx,0:ny,0:nz)
336
      character*80         fieldname
337
      character*80         pvsrcfile
338
      real                 dx,dy,dz,xmin,ymin,zmin
339
      real                 mdv
340
 
341
c     Numerical and physical parameters
342
      real                 eps
343
      parameter            (eps=0.01)
344
 
345
c     Auxiliary variables
346
      integer              cdfid,stat,cdfid99
347
      integer              vardim(4)
348
      real                 misdat
349
      real                 varmin(4),varmax(4),stag(4)
350
      integer              ndimin,outid,i,j,k
351
      real                 tmp(nx,ny,nz)
352
      integer              ntimes
353
      real                 time(200)       
354
      integer              nvars
355
      character*80         vnam(100),varname
356
      integer              isok
357
 
358
c     Open the input netcdf file
359
      call cdfopn(pvsrcfile,cdfid,stat)
360
      if (stat.ne.0) goto 998
361
 
362
c     Check whether needed variables are on file
363
      call getvars(cdfid,nvars,vnam,stat)
364
      if (stat.ne.0) goto 998
365
      isok=0
366
      varname=trim(fieldname)
367
      call check_varok(isok,varname,vnam,nvars)
368
      if (isok.eq.0) goto 998
369
 
370
c     Get the grid parameters from theta     
371
      call getdef(cdfid,varname,ndimin,misdat,vardim,
372
     >            varmin,varmax,stag,stat)    
373
      if (stat.ne.0) goto 998
374
      time(1)=0.
375
      call gettimes(cdfid,time,ntimes,stat)  
376
      if (stat.ne.0) goto 998
377
 
378
c     Check whether grid parameters are consistent
379
      if ( (vardim(1).ne.(nx+1)).or.
380
     >     (vardim(2).ne.(ny+1)).or.
381
     >     (vardim(3).ne.(nz+1)).or.
382
     >     (abs(varmin(1)-xmin).gt.eps).or.
383
     >     (abs(varmin(2)-ymin).gt.eps).or.
384
     >     (abs(varmin(3)-zmin).gt.eps).or.
385
     >     (abs((varmax(1)-varmin(1))/real(vardim(1)-1)-dx).gt.eps).or.
386
     >     (abs((varmax(2)-varmin(2))/real(vardim(2)-1)-dy).gt.eps).or.
387
     >     (abs((varmax(3)-varmin(3))/real(vardim(3)-1)-dz).gt.eps) ) 
388
     >then
389
         print*,'Input grid inconsitency...'
390
         print*,'  Nx      = ',vardim(1),nx+1
391
         print*,'  Ny      = ',vardim(2),ny+1
392
         print*,'  Nz      = ',vardim(3),nz+1
393
         print*,'  Varminx = ',varmin(1),xmin
394
         print*,'  Varminy = ',varmin(2),ymin
395
         print*,'  Varminz = ',varmin(3),zmin
396
         print*,'  Dx      = ',(varmax(1)-varmin(1))/real(nx-1),dx
397
         print*,'  Dy      = ',(varmax(2)-varmin(2))/real(ny-1),dy
398
         print*,'  Dz      = ',(varmax(3)-varmin(3))/real(nz-1),dz
399
         goto 998
400
      endif
401
 
402
c     Load variables
403
      call getdef(cdfid,varname,ndimin,misdat,vardim,
404
     >            varmin,varmax,stag,stat)
405
      if (stat.ne.0) goto 998
406
      call getdat(cdfid,varname,time(1),0,field,stat)
407
      print*, 'R ',trim(varname),' ',trim(pvsrcfile)
408
      if (stat.ne.0) goto 998
409
 
410
c     Close input netcdf file
411
      call clscdf(cdfid,stat)
412
      if (stat.ne.0) goto 998
413
 
414
c     Set missing data value to <mdv>
415
      do i=1,nx
416
         do j=1,ny
417
            do k=1,nz
418
               if (abs(field(i,j,k)-misdat).lt.eps) then
419
                  field(i,j,k)=mdv
420
               endif
421
            enddo
422
         enddo
423
      enddo
424
 
425
      return
426
 
427
c     Exception handling
428
 998  print*,'Read_Inp: Problem with input netcdf file... Stop'
429
      stop
430
 
431
      end
432
 
433
c     --------------------------------------------------------------------------------
434
c     Read refernece profile from netcdf
435
c     --------------------------------------------------------------------------------
436
 
437
      SUBROUTINE read_ref (nsqref,rhoref,thetaref,pressref,zref,
438
     >                     nx,ny,nz,deltax,deltay,deltaz,coriol,oro,
439
     >                     pvsrcfile) 
440
 
441
c     Read the reference profile from file
442
c
443
c         thetaref             : Reference potential temperature (K)
444
c         pressref             : Reference pressure (Pa)
445
c         rhoref               : Reference density (kg/m^3)
446
c         nsqref               : Stratification (s^-1)
447
c         zref                 : Reference height (m)
448
c         nx,nny,nz            : Grid dimension in x,y,z direction
449
c         deltax,deltay,deltaz : Grid spacings used for calculations (m)
450
c         coriol               : Coriolis parameter (s^-1)
451
c         oro                  : Height of orography (m)
452
c         pvsrcfile            : Input file
453
 
454
      implicit   none
455
 
456
c     Declaration of subroutine parameters
457
      integer              nx,ny,nz
458
      real                 nsqref  (0:2*nz)
459
      real                 thetaref(0:2*nz)
460
      real                 rhoref  (0:2*nz)
461
      real                 pressref(0:2*nz)
462
      real                 zref    (0:2*nz)
463
      real                 deltax,deltay,deltaz
464
      real                 coriol  (0:nx,0:ny)
465
      real                 oro     (0:nx,0:ny)
466
      character*80         pvsrcfile
467
 
468
c     Numerical and physical parameters
469
      real                 eps
470
      parameter            (eps=0.01)
471
 
472
c     Auxiliary variables
473
      integer              cdfid,stat
474
      integer              vardim(4)
475
      real                 misdat
476
      integer              ndimin
477
      real                 varmin(4),varmax(4),stag(4)
478
      integer              i,j,k,nf1
479
      integer              ntimes
480
      real                 time(200)  
481
      character*80         vnam(100),varname
482
      integer              nvars
483
      integer              isok,ierr
484
      real                 x(0:nx,0:ny),y(0:nx,0:ny)
485
      real                 mean,count
486
 
487
c     Get grid description from topography
488
      call cdfopn(pvsrcfile,cdfid,stat)
489
      if (stat.ne.0) goto 997
490
      call getvars(cdfid,nvars,vnam,stat)
491
      if (stat.ne.0) goto 997
492
      isok=0
493
      varname='ORO'
494
      call check_varok(isok,varname,vnam,nvars)
495
      if (isok.eq.0) goto 997
496
      call getdef(cdfid,varname,ndimin,misdat,vardim,
497
     >            varmin,varmax,stag,stat)    
498
      if (stat.ne.0) goto 997
499
      time(1)=0.
500
      call gettimes(cdfid,time,ntimes,stat)  
501
      if (stat.ne.0) goto 997
502
      call clscdf(cdfid,stat)
503
      if (stat.ne.0) goto 997
504
 
505
c     Open output netcdf file
506
      call cdfopn(pvsrcfile,cdfid,stat)
507
      if (stat.ne.0) goto 997
508
 
509
c     Create the variable if necessary
510
      call getvars(cdfid,nvars,vnam,stat)
511
      if (stat.ne.0) goto 997
512
 
513
c     Read data from netcdf file
514
      isok=0
515
      varname='NSQREF'
516
      print*,'R ',trim(varname),' ',trim(pvsrcfile)
517
      call check_varok(isok,varname,vnam,nvars)
518
      if (isok.eq.0) goto 997
519
      call getdat(cdfid,varname,time(1),0,nsqref,stat)
520
      if (stat.ne.0) goto 997
521
 
522
      isok=0
523
      varname='RHOREF'
524
      print*,'R ',trim(varname),' ',trim(pvsrcfile)
525
      call check_varok(isok,varname,vnam,nvars)
526
      if (isok.eq.0) goto 997
527
      call getdat(cdfid,varname,time(1),0,rhoref,stat)
528
      if (stat.ne.0) goto 997
529
 
530
      isok=0
531
      varname='THETAREF'
532
      print*,'R ',trim(varname),' ',trim(pvsrcfile)
533
      call check_varok(isok,varname,vnam,nvars)
534
      if (isok.eq.0) goto 997
535
      call getdat(cdfid,varname,time(1),0,thetaref,stat)
536
      if (stat.ne.0) goto 997
537
 
538
      isok=0
539
      varname='PREREF'
540
      print*,'R ',trim(varname),' ',trim(pvsrcfile)
541
      call check_varok(isok,varname,vnam,nvars)
542
      if (isok.eq.0) goto 997
543
      call getdat(cdfid,varname,time(1),0,pressref,stat)
544
      if (stat.ne.0) goto 997
545
 
546
      isok=0
547
      varname='ZREF'
548
      print*,'R ',trim(varname),' ',trim(pvsrcfile)
549
      call check_varok(isok,varname,vnam,nvars)
550
      if (isok.eq.0) goto 997
551
      call getdat(cdfid,varname,time(1),0,zref,stat)
552
      if (stat.ne.0) goto 997
553
 
554
      isok=0
555
      varname='CORIOL'
556
      print*,'R ',trim(varname),' ',trim(pvsrcfile)
557
      call check_varok(isok,varname,vnam,nvars)
558
      if (isok.eq.0) goto 997
559
      call getdat(cdfid,varname,time(1),0,coriol,stat)
560
      if (stat.ne.0) goto 997
561
 
562
      isok=0
563
      varname='ORO'
564
      print*,'R ',trim(varname),' ',trim(pvsrcfile)
565
      call check_varok(isok,varname,vnam,nvars)
566
      if (isok.eq.0) goto 997
567
      call getdat(cdfid,varname,time(1),0,oro,stat)
568
      if (stat.ne.0) goto 997
569
 
570
      isok=0
571
      varname='X'
572
      print*,'R ',trim(varname),' ',trim(pvsrcfile)
573
      call check_varok(isok,varname,vnam,nvars)
574
      if (isok.eq.0) goto 997
575
      call getdat(cdfid,varname,time(1),0,x,stat)
576
      if (stat.ne.0) goto 997
577
 
578
      isok=0
579
      varname='Y'
580
      print*,'R ',trim(varname),' ',trim(pvsrcfile)
581
      call check_varok(isok,varname,vnam,nvars)
582
      if (isok.eq.0) goto 997
583
      call getdat(cdfid,varname,time(1),0,y,stat)
584
      if (stat.ne.0) goto 997
585
 
586
c     Close  netcdf file
587
      call clscdf(cdfid,stat)
588
      if (stat.ne.0) goto 997
589
 
590
c     Determine the grid spacings <deltax, deltay, deltaz>
591
      mean=0.
592
      count=0.
593
      do i=1,nx
594
         do j=0,ny
595
            mean=mean+abs(x(i)-x(i-1))
596
            count=count+1.
597
         enddo
598
      enddo
599
      deltax=mean/count
600
 
601
      mean=0.
602
      count=0.
603
      do j=1,ny
604
         do i=0,nx
605
            mean=mean+abs(y(j)-y(j-1))
606
            count=count+1.
607
         enddo
608
      enddo
609
      deltay=mean/count
610
 
611
      mean=0.
612
      count=0.
613
      do k=1,nz-1
614
         mean=mean+abs(zref(k+1)-zref(k-1))
615
         count=count+1.
616
      enddo
617
      deltaz=mean/count
618
 
619
      return
620
 
621
c     Exception handling
622
 997  print*,'Read_Ref: Problem with input netcdf file... Stop'
623
      stop
624
 
625
      end
626
 
627
c     --------------------------------------------------------------------------------
628
c     Check whether variable is found on netcdf file
629
c     --------------------------------------------------------------------------------
630
 
631
      subroutine check_varok (isok,varname,varlist,nvars)
632
 
633
c     Check whether the variable <varname> is in the list <varlist(nvars)>. If this is 
634
C     the case, <isok> is incremented by 1. Otherwise <isok> keeps its value.
635
 
636
      implicit none
637
 
638
c     Declaraion of subroutine parameters
639
      integer      isok
640
      integer      nvars
641
      character*80 varname
642
      character*80 varlist(nvars)
643
 
644
c     Auxiliary variables
645
      integer      i
646
 
647
c     Main
648
      do i=1,nvars
649
         if (trim(varname).eq.trim(varlist(i))) isok=isok+1
650
      enddo
651
 
652
      end
653
 
654
c     --------------------------------------------------------------------------------
655
c     Get grid parameters
656
c     --------------------------------------------------------------------------------
657
 
658
      subroutine read_dim (nx,ny,nz,dx,dy,dz,xmin,ymin,zmin,mdv,
659
     >                     pvsrcfile)
660
 
661
c     Get the grid parameters from the variable <THETA> on the input file <pvsrcfile>.
662
c     The grid parameters are
663
c        nx,ny,nz                : Number of grid points in x, y and z direction
664
c        xmin,ymin,zmin          : Minimum domain coordinates in x, y and z direction
665
c        xmax,ymax,zmax          : Maximal domain coordinates in x, y and z direction
666
c        dx,dy,dz                : Horizontal and vertical resolution
667
c     Additionally, it is checked whether the vertical grid is equally spaced. If ok,
668
c     the grid paramters are transformed from lon/lat to distance (in meters)
669
 
670
      implicit none
671
 
672
c     Declaration of subroutine parameters
673
      character*80   pvsrcfile
674
      integer        nx,ny,nz
675
      real           dx,dy,dz
676
      real           xmin,ymin,zmin,xmax,ymax,zmax
677
      real           mdv
678
 
679
c     Numerical epsilon and other physical/geoemtrical parameters
680
      real           eps
681
      parameter      (eps=0.01)
682
 
683
c     Auxiliary variables
684
      integer        cdfid,cstid
685
      integer        ierr
686
      character*80   vnam(100),varname
687
      integer        nvars
688
      integer        isok
689
      integer        vardim(4)
690
      real           misdat
691
      real           varmin(4),varmax(4),stag(4)
692
      real           aklev(1000),bklev(1000),aklay(1000),bklay(1000)
693
      real           dh
694
      character*80   csn
695
      integer        ndim
696
      integer        i
697
 
698
c     Get all grid parameters
699
      call cdfopn(pvsrcfile,cdfid,ierr)
700
      if (ierr.ne.0) goto 998
701
      call getvars(cdfid,nvars,vnam,ierr)
702
      if (ierr.ne.0) goto 998
703
      isok=0
704
      varname='PV'
705
      call check_varok(isok,varname,vnam,nvars)
706
      if (isok.eq.0) goto 998
707
      call getcfn(cdfid,csn,ierr)
708
      if (ierr.ne.0) goto 998
709
      call cdfopn(csn,cstid,ierr)
710
      if (ierr.ne.0) goto 998
711
      call getdef(cdfid,varname,ndim,misdat,vardim,varmin,varmax,
712
     >            stag,ierr)
713
      if (ierr.ne.0) goto 998
714
      nx=vardim(1)
715
      ny=vardim(2)
716
      nz=vardim(3)
717
      xmin=varmin(1)
718
      ymin=varmin(2)
719
      zmin=varmin(3)
720
      call getlevs(cstid,nz,aklev,bklev,aklay,bklay,ierr)
721
      if (ierr.ne.0) goto 998
722
      call getgrid(cstid,dx,dy,ierr)
723
      if (ierr.ne.0) goto 998
724
      xmax=varmax(1)
725
      ymax=varmax(2)
726
      zmax=varmax(3)
727
      dz=(zmax-zmin)/real(nz-1)
728
      call clscdf(cstid,ierr)
729
      if (ierr.ne.0) goto 998
730
      call clscdf(cdfid,ierr)
731
      if (ierr.ne.0) goto 998
732
 
733
c     Check whether the grid is equallay spaced in the vertical
734
      do i=1,nz-1
735
         dh=aklev(i+1)-aklev(i)
736
         if (abs(dh-dz).gt.eps) then
737
            print*,'Aklev: Vertical grid must be equally spaced... Stop'
738
            print*,(aklev(i),i=1,nz)
739
            stop
740
         endif
741
         dh=aklay(i+1)-aklay(i)
742
         if (abs(dh-dz).gt.eps) then
743
            print*,'Aklay: Vertical grid must be equally spaced... Stop'
744
            print*,(aklay(i),i=1,nz)
745
            stop
746
         endif
747
      enddo
748
 
749
c     Set missing data value
750
      mdv=misdat
751
 
752
      return
753
 
754
c     Exception handling
755
 998  print*,'Read_Dim: Problem with input netcdf file... Stop'
756
      stop
757
 
758
      end
759
 
760
 
761
c     ********************************************************************************
762
c     * CALCULATION                                                                  *
763
c     ********************************************************************************
764
 
765
c     --------------------------------------------------------------------------------
766
c     Calculate qgPV from Ertels's PV 
767
c     --------------------------------------------------------------------------------               
768
 
769
      subroutine epv_to_qgpv (qgpv,pv,
770
     >                        rhoref,pressref,nsqref,thetaref,
771
     >                        nx,ny,nz,mdv)
772
 
773
c     Calculate the qgPV from Ertel's PV according to equation 2.11 p16, Thesis 
774
c     from Rene Fehlmann.
775
 
776
      implicit none
777
 
778
c     Declaration of subroutine parameters
779
      integer   nx,ny,nz
780
      real      qgpv(0:nx,0:ny,0:nz),pv(0:nx,0:ny,0:nz)
781
      real      rhoref  (0:2*nz)
782
      real      nsqref  (0:2*nz)
783
      real      thetaref(0:2*nz)
784
      real      pressref(0:2*nz)
785
      real      mdv
786
 
787
c     Numerical epsilon
788
      real       g
789
      parameter  (g=9.81)
790
      real       eps
791
      parameter  (eps=0.01)
792
      real       scale
793
      parameter  (scale=1e6)
794
 
795
c     Auxiliary variables
796
      integer i,j,k
797
      integer kk
798
 
799
c     Calculation
800
      do i=0,nx
801
         do j=0,ny
802
            do k=0,nz
803
 
804
               kk=2*k
805
 
806
               if (( abs(rhoref(kk)  -mdv).gt.eps).and. 
807
     >             ( abs(thetaref(kk)-mdv).gt.eps).and. 
808
     >             ( abs(nsqref(kk)  -mdv).gt.eps).and. 
809
     >             ( abs(pv(i,j,k)   -mdv).gt.eps)) then
810
 
811
                  qgpv(i,j,k)=rhoref(kk)*g*pv(i,j,k)/thetaref(kk)/ 
812
     >                        nsqref(kk)/scale
813
 
814
               else
815
                  qgpv(i,j,k)=0.
816
               endif
817
 
818
            enddo
819
         enddo
820
      enddo
821
 
822
      end
823
 
824
c     --------------------------------------------------------------------------------
825
c     Calculate error statistics
826
c     --------------------------------------------------------------------------------               
827
 
828
      subroutine calc_error (min,max,mean,rmsq,tmp,nx,ny)
829
 
830
c     Calculate the error statistics for the two-dimensional error field <tmp>. The
831
c     following error measures are calculated: the minimum <min>, the maximum <max>,
832
c     the mean <mean>, the root-mean square <rmsq>
833
 
834
      implicit none
835
 
836
c     Declaration of subroutine parameters
837
      integer nx,ny
838
      real    tmp(0:nx,0:ny)
839
      real    mean,rmsq
840
      real    min,max
841
 
842
c     Auxiliary variables
843
      integer i,j
844
      real    sum
845
      integer cnt
846
 
847
c     Calculate the minimum and maximum
848
      min=tmp(0,0)
849
      max=tmp(0,0)
850
      do i=0,nx
851
         do j=0,ny
852
            if (tmp(i,j).lt.min) min=tmp(i,j)
853
            if (tmp(i,j).gt.max) max=tmp(i,j)
854
         enddo
855
      enddo
856
 
857
c     Calculate the mean
858
      sum=0.
859
      cnt=0
860
      do i=0,nx
861
         do j=0,ny
862
            cnt=cnt+1
863
            sum=sum+tmp(i,j)
864
         enddo
865
      enddo
866
      if (cnt.ge.1) then
867
         mean=sum/real(cnt)
868
      else
869
         mean=0.
870
      endif
871
 
872
c     Calculate rmsq
873
      rmsq=0.
874
      cnt=0
875
      do i=0,nx
876
         do j=0,ny
877
            cnt=cnt+1
878
            rmsq=rmsq+(tmp(i,j)-mean)**2
879
         enddo
880
      enddo
881
      if (cnt.ge.1) then
882
         rmsq=1./real(cnt)*sqrt(rmsq)
883
      else
884
         rmsq=0.
885
      endif
886
 
887
      end
888
 
889
 
890
 
891
 
892
 
893
 
894