Subversion Repositories pvinversion.ecmwf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 michaesp 1
 
2
      PROGRAM def_anomaly
3
 
4
c     ************************************************************************
5
c     * Define a PV anomaly and set it up for inversion. Additionally, the   *
6
c     * lateral and upper/lower boundary values for potential temperature    *
7
c     * and wind are set                                                     *
8
c     * Michael Sprenger / Spring 2005                                       *
9
c     ************************************************************************
10
 
11
      implicit none
12
 
13
c     ------------------------------------------------------------------------
14
c     Declaration of subroutine parameters
15
c     ------------------------------------------------------------------------
16
 
17
c     Numerical epsilon
18
      real         eps
19
      parameter    (eps=0.01)
20
 
21
c     Variables for input Z file  : height level
22
      character*80 in_zfn,in_varname
23
      real         in_varmin(4),in_varmax(4),in_stag(4)
24
      integer      in_vardim(4)
25
      real         in_mdv
26
      integer      in_ndim
27
      integer      in_nx,in_ny,in_nz
28
      real         in_xmin,in_xmax,in_ymin,in_ymax,in_dx,in_dy
29
      integer      in_ntimes
30
      real         in_aklev(1000),in_bklev(1000)
31
      real         in_aklay(1000),in_bklay(1000)
32
 
33
      real         in_time
34
      real         in_pollon,in_pollat
35
      integer      in_idate(5)
36
      integer      in_nvars
37
      character*80 in_vnam(100)
38
      real,allocatable, dimension (:,:,:)    :: in_field
39
      real,allocatable, dimension (:,:,:)    :: in_filt
40
      real,allocatable, dimension (:,:,:)    :: in_anom
41
      real,allocatable, dimension (:,:)      :: in_x,in_y
42
      real,allocatable, dimension (:,:,:)    :: th_anom
43
      real,allocatable, dimension (:,:,:)    :: uu_anom,vv_anom
44
 
45
c     Filtering
46
      real          f_xmin,f_xmax
47
      real          f_ymin,f_ymax
48
      real          f_zmin,f_zmax
49
      integer       nfilt
50
      real          boundxy,boundz
51
      real,allocatable, dimension (:,:)      :: tmp
52
 
53
c     Auxiliary variables
54
      integer      i,j,k,l,n
55
      integer      cdfid,cstid
56
      integer      ierr,stat
57
      character*80 cfn
58
      real         xpt,ypt,zpt
59
      integer      isok
60
      character*80 varname,cdfname
61
      character*80 parfile
62
      real         distxy,distz,distz1,distz2
63
      integer      indx,indy,indz
64
      real         sum
65
      integer      count
66
      character*80 name
67
 
68
c     Externals
69
      real         kink
70
      external     kink
71
 
72
c     ------------------------------------------------------------------------
73
c     Preparations
74
c     ------------------------------------------------------------------------
75
 
76
      print*,'*********************************************************'
77
      print*,'* def_anomaly                                           *'
78
      print*,'*********************************************************'
79
 
80
c     Set name of the PV variable
81
      in_varname='PV'
82
 
83
c     Read parameters
84
      open(10,file='fort.10')
85
       read(10,*) in_zfn
86
       read(10,*) name,f_xmin
87
       if ( trim(name).ne.'BOX_XMIN') stop
88
       read(10,*) name,f_xmax
89
       if ( trim(name).ne.'BOX_XMAX') stop
90
       read(10,*) name,f_ymin
91
       if ( trim(name).ne.'BOX_YMIN') stop
92
       read(10,*) name,f_ymax
93
       if ( trim(name).ne.'BOX_YMAX') stop
94
       read(10,*) name,f_zmin
95
       if ( trim(name).ne.'BOX_ZMIN') stop
96
       read(10,*) name,f_zmax
97
       if ( trim(name).ne.'BOX_ZMAX') stop
98
       read(10,*) name,nfilt
99
       if ( trim(name).ne.'NFILTER' ) stop
100
       read(10,*) name,boundxy
101
       if ( trim(name).ne.'BOUND_XY') stop
102
       read(10,*) name,boundz
103
       if ( trim(name).ne.'BOUND_Z')  stop
104
      close(10)
105
 
106
      print*,'Filter domain, x: ', f_xmin,f_xmax
107
      print*,'               y: ', f_ymin,f_ymax
108
      print*,'               z: ', f_zmin,f_zmax
109
      print*,'Nfilt:            ',nfilt
110
      print*,'Boundxy,z:        ',boundxy,boundz
111
 
112
c     Get grid description for Z file : height levels
113
      call cdfopn(in_zfn,cdfid,ierr)
114
      if (ierr.ne.0) goto 998
115
      call getcfn(cdfid,cfn,ierr)
116
      if (ierr.ne.0) goto 998
117
      call cdfopn(cfn,cstid,ierr)
118
      if (ierr.ne.0) goto 998
119
      call getvars(cdfid,in_nvars,in_vnam,ierr)
120
      if (ierr.ne.0) goto 998
121
      call getdef(cdfid,in_varname,in_ndim,in_mdv,in_vardim,
122
     >            in_varmin,in_varmax,in_stag,ierr)
123
      if (ierr.ne.0) goto 998
124
      in_nx  =in_vardim(1)
125
      in_ny  =in_vardim(2)
126
      in_nz  =in_vardim(3)
127
      in_xmin=in_varmin(1)
128
      in_ymin=in_varmin(2)
129
      call getlevs(cstid,in_nz,in_aklev,in_bklev,in_aklay,in_bklay,ierr)
130
      if (ierr.ne.0) goto 998
131
      call getgrid(cstid,in_dx,in_dy,ierr)
132
      if (ierr.ne.0) goto 998
133
      in_xmax=in_xmin+real(in_nx-1)*in_dx
134
      in_ymax=in_ymin+real(in_ny-1)*in_dy
135
      call gettimes(cdfid,in_time,in_ntimes,ierr)
136
      if (ierr.ne.0) goto 998
137
      call getstart(cstid,in_idate,ierr)
138
      if (ierr.ne.0) goto 998
139
      call getpole(cstid,in_pollon,in_pollat,ierr)
140
      if (ierr.ne.0) goto 998
141
      call clscdf(cstid,ierr)
142
      if (ierr.ne.0) goto 998
143
      call clscdf(cdfid,ierr)
144
 
145
c     Allocate memory for grid description
146
      allocate(in_x(in_nx,in_ny),stat=stat)
147
      if (stat.ne.0) print*,'*** error allocating array in_x ***'    
148
      allocate(in_y(in_nx,in_ny),stat=stat)
149
      if (stat.ne.0) print*,'*** error allocating array in_y ***'    
150
 
151
c     Allocate memory for input and output fields
152
      allocate(in_field(in_nx,in_ny,in_nz),stat=stat)
153
      if (stat.ne.0) print*,'*** error allocating array in_field ***'
154
      allocate(in_anom(in_nx,in_ny,in_nz),stat=stat)
155
      if (stat.ne.0) print*,'*** error allocating array in_anom ***'
156
      allocate(in_filt(in_nx,in_ny,in_nz),stat=stat)
157
      if (stat.ne.0) print*,'*** error allocating array in_filt ***'
158
      allocate(th_anom(in_nx,in_ny,in_nz),stat=stat)
159
      if (stat.ne.0) print*,'*** error allocating array th_anom ***'
160
      allocate(uu_anom(in_nx,in_ny,in_nz),stat=stat)
161
      if (stat.ne.0) print*,'*** error allocating array uu_anom ***'
162
      allocate(vv_anom(in_nx,in_ny,in_nz),stat=stat)
163
      if (stat.ne.0) print*,'*** error allocating array vvnom ***'
164
 
165
c     Allocate memory for filtering
166
      allocate(tmp(in_nx,in_ny),stat=stat)
167
      if (stat.ne.0) print*,'*** error allocating array tmp ***'
168
 
169
c     Read variables from file
170
      call cdfopn(in_zfn,cdfid,ierr)
171
      if (ierr.ne.0) goto 998
172
 
173
      varname=trim(in_varname)
174
      print*,'R ',trim(varname),'   ',trim(in_zfn)
175
      call gettimes(cdfid,in_time,in_ntimes,ierr)
176
      if (ierr.ne.0) goto 998
177
      call getdat(cdfid,varname,in_time,0,in_field,ierr)
178
      if (ierr.ne.0) goto 998
179
 
180
      varname='X'
181
      print*,'R ',trim(varname),'   ',trim(in_zfn)
182
      call gettimes(cdfid,in_time,in_ntimes,ierr)
183
      if (ierr.ne.0) goto 998
184
      call getdat(cdfid,varname,in_time,0,in_x,ierr)
185
      if (ierr.ne.0) goto 998
186
 
187
      varname='Y'
188
      print*,'R ',trim(varname),'   ',trim(in_zfn)
189
      call gettimes(cdfid,in_time,in_ntimes,ierr)
190
      if (ierr.ne.0) goto 998
191
      call getdat(cdfid,varname,in_time,0,in_y,ierr)
192
      if (ierr.ne.0) goto 998
193
 
194
      call clscdf(cdfid,ierr)
195
      if (ierr.ne.0) goto 998
196
 
197
c     ------------------------------------------------------------------------
198
c     Get the average along the x axis: "zonal" average
199
c     ------------------------------------------------------------------------
200
 
201
      print*,'A ',trim(in_varname)
202
      do k=1,in_nz
203
         do j=1,in_ny
204
 
205
c           Get the mean along x axis
206
            sum=0.
207
            count=0
208
            do i=1,in_nx
209
               if (abs(in_field(i,j,k)-in_mdv).gt.eps) then
210
                  sum=sum+in_field(i,j,k)
211
                  count=count+1
212
               endif
213
            enddo
214
            if (count.ge.1) then
215
               sum=sum/real(count)
216
            else
217
               sum=in_mdv
218
            endif
219
 
220
c           Get the difference relative to the "zonal" mean
221
            do i=1,in_nx
222
               xpt=in_x(i,j)
223
               ypt=in_y(i,j)
224
               zpt=in_aklay(k)
225
               if ( (xpt.ge.f_xmin).and.
226
     >              (xpt.le.f_xmax).and.
227
     >              (ypt.ge.f_ymin).and.
228
     >              (ypt.le.f_ymax).and.
229
     >              (zpt.ge.f_zmin).and.
230
     >              (zpt.le.f_zmax)) then
231
                  in_filt(i,j,k)=sum
232
               else
233
                  in_filt(i,j,k)=in_field(i,j,k)
234
               endif
235
            enddo
236
 
237
         enddo
238
      enddo
239
 
240
c     ------------------------------------------------------------------------
241
c     Get the anomaly field
242
c     ------------------------------------------------------------------------
243
c 
244
c     Determine the difference between filtered and unfiltered field
245
      do i=1,in_nx
246
         do j=1,in_ny
247
            do k=1,in_nz
248
               if ( (abs(in_field(i,j,k)-in_mdv).gt.eps).and.
249
     >              (abs(in_filt (i,j,k)-in_mdv).gt.eps)) then
250
                  in_anom(i,j,k)=in_field(i,j,k)-in_filt(i,j,k)
251
               else
252
                  in_anom(i,j,k)=in_mdv
253
               endif
254
            enddo
255
         enddo
256
      enddo
257
 
258
c     Take only the positive part of the difference (mdv is set to 0)
259
      do i=1,in_nx
260
         do j=1,in_ny
261
            do k=1,in_nz
262
               if ( (abs(in_anom(i,j,k)-in_mdv).lt.eps) ) then
263
                  in_anom(i,j,k)=0.
264
               else if ( in_anom(i,j,k).lt.0.) then
265
                  in_anom(i,j,k)=0.
266
               endif
267
            enddo
268
         enddo
269
      enddo
270
 
271
c     Smooth transition to zero at boundaries
272
      do i=1,in_nx
273
         do j=1,in_ny
274
            do k=1,in_nz
275
               if ( (abs(in_anom (i,j,k)-in_mdv).gt.eps) ) then
276
 
277
                  in_anom(i,j,k)=in_anom(i,j,k)*
278
     >                            kink(f_zmax     -in_aklay(k),boundz )*
279
     >                            kink(in_aklay(k)-f_zmin     ,boundz )*
280
     >                            kink(in_x(i,j)  -f_xmin     ,boundxy)*
281
     >                            kink(f_xmax     -in_x(i,j)  ,boundxy)*
282
     >                            kink(in_y(i,j)  -f_ymin     ,boundxy)*
283
     >                            kink(f_ymax     -in_y(i,j)  ,boundxy)
284
 
285
               endif
286
            enddo
287
         enddo
288
      enddo      
289
 
290
c     ------------------------------------------------------------------------
291
c     Apply a digital filter to the anomaly field
292
c     ------------------------------------------------------------------------
293
 
294
      print*,'F ',trim(in_varname)
295
      do k=1,in_nz
296
 
297
         do i=1,in_nx
298
            do j=1,in_ny
299
               tmp(i,j)=in_anom(i,j,k)
300
            enddo
301
         enddo
302
 
303
         do n=1,nfilt     
304
            call filt2d (tmp,tmp,in_nx,in_ny,1.,in_mdv,0,0,0,0)
305
         enddo
306
 
307
         do i=1,in_nx
308
            do j=1,in_ny
309
               in_anom(i,j,k)=tmp(i,j)
310
            enddo
311
         enddo
312
 
313
      enddo
314
 
315
c     ------------------------------------------------------------------------
316
c     Get the modified PV field (original minus anomaly)
317
c     ------------------------------------------------------------------------
318
 
319
      do i=1,in_nx
320
         do j=1,in_ny
321
            do k=1,in_nz 
322
               if ( (abs(in_anom (i,j,k)-in_mdv).gt.eps).and.
323
     >              (abs(in_field(i,j,k)-in_mdv).gt.eps) ) then
324
                  in_filt(i,j,k)=in_field(i,j,k)-in_anom(i,j,k)
325
               else
326
                  in_filt(i,j,k)=in_mdv
327
               endif
328
            enddo
329
         enddo
330
      enddo
331
 
332
c     -----------------------------------------------------------------
333
c     Define the boundary values for wind and potential temperature
334
c     -----------------------------------------------------------------
335
 
336
      do i=1,in_nx
337
         do j=1,in_ny
338
            do k=1,in_nz
339
               th_anom(i,j,k)=0.
340
               uu_anom(i,j,k)=0.
341
               vv_anom(i,j,k)=0.
342
            enddo
343
         enddo
344
      enddo
345
 
346
c     -----------------------------------------------------------------
347
c     Write output
348
c     -----------------------------------------------------------------
349
 
350
c     Open output netcdf file
351
      call cdfwopn(in_zfn,cdfid,ierr)
352
      if (ierr.ne.0) goto 997
353
 
354
c     Write the 3d filtered field
355
      isok=0
356
      varname=trim(in_varname)//'_FILT'
357
      print*,'Write ',trim(varname),'  ',trim(in_zfn)
358
      call check_varok(isok,varname,in_vnam,in_nvars)
359
      if (isok.eq.0) then
360
         call putdef(cdfid,varname,4,in_mdv,in_vardim,
361
     >               in_varmin,in_varmax,in_stag,ierr)
362
         if (ierr.ne.0) goto 997
363
      endif
364
      call putdat(cdfid,varname,in_time,0,in_filt,ierr)
365
      if (ierr.ne.0) goto 997
366
 
367
c     Write the 3d anomaly field
368
      isok=0
369
      varname=trim(in_varname)//'_ANOM'
370
      print*,'Write ',trim(varname),'  ',trim(in_zfn)
371
      call check_varok(isok,varname,in_vnam,in_nvars)
372
      if (isok.eq.0) then
373
         call putdef(cdfid,varname,4,in_mdv,in_vardim,
374
     >               in_varmin,in_varmax,in_stag,ierr)
375
         if (ierr.ne.0) goto 997
376
      endif
377
      call putdat(cdfid,varname,in_time,0,in_anom,ierr)
378
      if (ierr.ne.0) goto 997
379
 
380
c     Write lower and upper boundary
381
      isok=0
382
      varname='TH_ANOM'
383
      print*,'Write ',trim(varname),'  ',trim(in_zfn)
384
      call check_varok(isok,varname,in_vnam,in_nvars)
385
      if (isok.eq.0) then
386
         call putdef(cdfid,varname,4,in_mdv,in_vardim,
387
     >               in_varmin,in_varmax,in_stag,ierr)
388
         if (ierr.ne.0) goto 997
389
      endif
390
      call putdat(cdfid,varname,in_time,0,th_anom,ierr)
391
      if (ierr.ne.0) goto 997
392
 
393
c     Write lateral boundary 
394
      isok=0
395
      varname='UU_ANOM'
396
      print*,'Write ',trim(varname),'  ',trim(in_zfn)
397
      call check_varok(isok,varname,in_vnam,in_nvars)
398
      if (isok.eq.0) then
399
         call putdef(cdfid,varname,4,in_mdv,in_vardim,
400
     >               in_varmin,in_varmax,in_stag,ierr)
401
         if (ierr.ne.0) goto 997
402
      endif
403
      call putdat(cdfid,varname,in_time,0,uu_anom,ierr)
404
      if (ierr.ne.0) goto 997
405
      isok=0
406
      varname='VV_ANOM'
407
      print*,'Write ',trim(varname),'  ',trim(in_zfn)
408
      call check_varok(isok,varname,in_vnam,in_nvars)
409
      if (isok.eq.0) then
410
         call putdef(cdfid,varname,4,in_mdv,in_vardim,
411
     >               in_varmin,in_varmax,in_stag,ierr)
412
         if (ierr.ne.0) goto 997
413
      endif
414
      call putdat(cdfid,varname,in_time,0,vv_anom,ierr)
415
      if (ierr.ne.0) goto 997
416
 
417
c     Close output netcdf file
418
      call clscdf(cdfid,ierr)
419
      if (ierr.ne.0) goto 997
420
 
421
 
422
c     -----------------------------------------------------------------
423
c     Exception handling and format specs
424
c     -----------------------------------------------------------------
425
 
426
      stop
427
 
428
 998  print*,'Problems with input netcdf file'
429
      stop
430
 
431
 997  print*,'Problems with output netcdf file'
432
      stop
433
 
434
      END
435
 
436
 
437
c     ******************************************************************
438
c     * 2D FILTERING                                                   *
439
c     ******************************************************************
440
 
441
c     -----------------------------------------------------------------
442
c     Horizontal filter
443
c     -----------------------------------------------------------------
444
 
445
      subroutine filt2d (a,af,nx,ny,fil,misdat,
446
     &                   iperx,ipery,ispol,inpol)
447
 
448
c     Apply a conservative diffusion operator onto the 2d field a,
449
c     with full missing data checking.
450
c
451
c     a     real   inp  array to be filtered, dimensioned (nx,ny)
452
c     af    real   out  filtered array, dimensioned (nx,ny), can be
453
c                       equivalenced with array a in the calling routine
454
c     f1    real        workarray, dimensioned (nx+1,ny)
455
c     f2    real        workarray, dimensioned (nx,ny+1)
456
c     fil   real   inp  filter-coeff., 0<afil<=1. Maximum filtering with afil=1
457
c                       corresponds to one application of the linear filter.
458
c     misdat real  inp  missing-data value, a(i,j)=misdat indicates that
459
c                       the corresponding value is not available. The
460
c                       misdat-checking can be switched off with with misdat=0.
461
c     iperx int    inp  periodic boundaries in the x-direction (1=yes,0=no)
462
c     ipery int    inp  periodic boundaries in the y-direction (1=yes,0=no)
463
c     inpol int    inp  northpole at j=ny  (1=yes,0=no)
464
c     ispol int    inp  southpole at j=1   (1=yes,0=no)
465
c
466
c     Christoph Schaer, 1993
467
 
468
c     argument declaration
469
      integer     nx,ny
470
      real        a(nx,ny),af(nx,ny),fil,misdat
471
      integer     iperx,ipery,inpol,ispol
472
 
473
c     local variable declaration
474
      integer     i,j,is
475
      real        fh
476
      real        f1(nx+1,ny),f2(nx,ny+1)
477
 
478
c     compute constant fh
479
      fh=0.125*fil
480
 
481
c     compute fluxes in x-direction
482
      if (misdat.eq.0.) then
483
        do j=1,ny
484
        do i=2,nx
485
          f1(i,j)=a(i-1,j)-a(i,j)
486
        enddo
487
        enddo
488
      else
489
        do j=1,ny
490
        do i=2,nx
491
          if ((a(i,j).eq.misdat).or.(a(i-1,j).eq.misdat)) then
492
            f1(i,j)=0.
493
          else
494
            f1(i,j)=a(i-1,j)-a(i,j)
495
          endif
496
        enddo
497
        enddo
498
      endif
499
      if (iperx.eq.1) then
500
c       do periodic boundaries in the x-direction
501
        do j=1,ny
502
          f1(1,j)=f1(nx,j)
503
          f1(nx+1,j)=f1(2,j)
504
        enddo
505
      else
506
c       set boundary-fluxes to zero
507
        do j=1,ny
508
          f1(1,j)=0.
509
          f1(nx+1,j)=0.
510
        enddo
511
      endif
512
 
513
c     compute fluxes in y-direction
514
      if (misdat.eq.0.) then
515
        do j=2,ny
516
        do i=1,nx
517
          f2(i,j)=a(i,j-1)-a(i,j)
518
        enddo
519
        enddo
520
      else
521
        do j=2,ny
522
        do i=1,nx
523
          if ((a(i,j).eq.misdat).or.(a(i,j-1).eq.misdat)) then
524
            f2(i,j)=0.
525
          else
526
            f2(i,j)=a(i,j-1)-a(i,j)
527
          endif
528
        enddo
529
        enddo
530
      endif
531
c     set boundary-fluxes to zero
532
      do i=1,nx
533
        f2(i,1)=0.
534
        f2(i,ny+1)=0.
535
      enddo
536
      if (ipery.eq.1) then
537
c       do periodic boundaries in the x-direction
538
        do i=1,nx
539
          f2(i,1)=f2(i,ny)
540
          f2(i,ny+1)=f2(i,2)
541
        enddo
542
      endif
543
      if (iperx.eq.1) then
544
        if (ispol.eq.1) then
545
c         do south-pole
546
          is=(nx-1)/2
547
          do i=1,nx
548
            f2(i,1)=-f2(mod(i-1+is,nx)+1,2)
549
          enddo
550
        endif
551
        if (inpol.eq.1) then
552
c         do north-pole
553
          is=(nx-1)/2
554
          do i=1,nx
555
            f2(i,ny+1)=-f2(mod(i-1+is,nx)+1,ny)
556
          enddo
557
        endif
558
      endif
559
 
560
c     compute flux-convergence -> filter
561
      if (misdat.eq.0.) then
562
        do j=1,ny
563
        do i=1,nx
564
            af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
565
        enddo
566
        enddo
567
      else
568
        do j=1,ny
569
        do i=1,nx
570
          if (a(i,j).eq.misdat) then
571
            af(i,j)=misdat
572
          else
573
            af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
574
          endif
575
        enddo
576
        enddo
577
      endif
578
 
579
      end
580
 
581
 
582
c     ******************************************************************
583
c     * AUXILIARY SUBROUTINES                                          *
584
c     ******************************************************************
585
 
586
C     -----------------------------------------------------------------
587
c     Rene's KINK function (for smoothing at bounadries)
588
C     -----------------------------------------------------------------
589
 
590
      real function kink (x,a)
591
 
592
      implicit none
593
 
594
c     declaration of parameters
595
      real   x,a
596
 
597
c     parameters
598
      real   pi
599
      parameter  (pi=3.1415926535)
600
 
601
      if (x.lt.0.) then
602
         kink=0.
603
      elseif (x.gt.a) then
604
         kink=1.
605
      else
606
         kink=(1.+cos(pi*(x-a)/a))/2.
607
      endif
608
 
609
      return
610
      end    
611
 
612
 
613
c     ---------------------------------------------------------
614
c     Subroutines to write the netcdf output file
615
c     ---------------------------------------------------------
616
 
617
      subroutine writecdf2D(cdfname,
618
     >                      varname,arr,time,
619
     >                      dx,dy,xmin,ymin,nx,ny,
620
     >                      crefile,crevar)
621
 
622
c     Create and write to the netcdf file <cdfname>. The variable
623
c     with name <varname> and with time <time> is written. The data
624
c     are in the two-dimensional array <arr>. The list <dx,dy,xmin,
625
c     ymin,nx,ny> specifies the output grid. The flags <crefile> and
626
c     <crevar> determine whether the file and/or the variable should
627
c     be created. 1: create / 0: not created
628
 
629
      IMPLICIT NONE
630
 
631
c     Declaration of input parameters
632
      character*80 cdfname,varname
633
      integer      nx,ny
634
      real         arr(nx,ny)
635
      real         dx,dy,xmin,ymin
636
      real         time
637
      integer      crefile,crevar
638
 
639
c     Further variables
640
      real         varmin(4),varmax(4),stag(4)
641
      integer      ierr,cdfid,ndim,vardim(4)
642
      character*80 cstname
643
      real         mdv
644
      integer      datar(14),stdate(5)
645
      integer      i
646
 
647
C     Definitions 
648
      varmin(1)=xmin
649
      varmin(2)=ymin
650
      varmin(3)=1050.
651
      varmax(1)=xmin+real(nx-1)*dx
652
      varmax(2)=ymin+real(ny-1)*dy
653
      varmax(3)=1050.
654
      cstname=trim(cdfname)//'_cst'
655
      ndim=4
656
      vardim(1)=nx
657
      vardim(2)=ny
658
      vardim(3)=1
659
      stag(1)=0.
660
      stag(2)=0.
661
      stag(3)=0.
662
      mdv=-999.98999
663
 
664
C     Create the file
665
      if (crefile.eq.0) then
666
         call cdfwopn(cdfname,cdfid,ierr)
667
         if (ierr.ne.0) goto 906
668
      else if (crefile.eq.1) then
669
         call crecdf(cdfname,cdfid,
670
     >        varmin,varmax,ndim,cstname,ierr)
671
         if (ierr.ne.0) goto 903 
672
 
673
C        Write the constants file
674
         datar(1)=vardim(1)
675
         datar(2)=vardim(2)
676
         datar(3)=int(1000.*varmax(2))
677
         datar(4)=int(1000.*varmin(1))
678
         datar(5)=int(1000.*varmin(2))
679
         datar(6)=int(1000.*varmax(1))
680
         datar(7)=int(1000.*dx)
681
         datar(8)=int(1000.*dy)
682
         datar(9)=1
683
         datar(10)=1
684
         datar(11)=0            ! data version
685
         datar(12)=0            ! cstfile version
686
         datar(13)=0            ! longitude of pole
687
         datar(14)=90000        ! latitude of pole     
688
         do i=1,5
689
            stdate(i)=0
690
         enddo
691
         call wricst(cstname,datar,0.,0.,0.,0.,stdate)
692
      endif
693
 
694
c     Write the data to the netcdf file, and close the file
695
      if (crevar.eq.1) then
696
         call putdef(cdfid,varname,ndim,mdv,
697
     >        vardim,varmin,varmax,stag,ierr)
698
         if (ierr.ne.0) goto 904
699
      endif
700
      call putdat(cdfid,varname,time,0,arr,ierr)
701
      if (ierr.ne.0) goto 905
702
      call clscdf(cdfid,ierr)
703
 
704
      return
705
 
706
c     Error handling
707
 903  print*,'*** Problem to create netcdf file ***'
708
      stop
709
 904  print*,'*** Problem to write definition ***'
710
      stop
711
 905  print*,'*** Problem to write data ***'
712
      stop
713
 906  print*,'*** Problem to open netcdf file ***'
714
      stop
715
 
716
      END
717
 
718
 
719
c     ------------------------------------------------------------------
720
c     Auxiliary routines
721
c     ------------------------------------------------------------------
722
 
723
      subroutine check_varok (isok,varname,varlist,nvars)
724
 
725
c     Check whether the variable <varname> is in the list <varlist(nvars)>. 
726
c     If this is the case, <isok> is incremented by 1. Otherwise <isok> keeps 
727
c     its value.
728
 
729
      implicit none
730
 
731
c     Declaraion of subroutine parameters
732
      integer      isok
733
      integer      nvars
734
      character*80 varname
735
      character*80 varlist(nvars)
736
 
737
c     Auxiliary variables
738
      integer      i
739
 
740
c     Main
741
      do i=1,nvars
742
         if (trim(varname).eq.trim(varlist(i))) isok=isok+1
743
      enddo
744
 
745
      end